/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 SIGNET LAB. Department of Information Engineering (DEI), University of Padua
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
* Original Work Authors:
*      Marco Mezzavilla <mezzavil@dei.unipd.it>
*      Giovanni Tomasi <tomasigv@gmail.com>
* Original Work Acknowldegments:
*      This work was supported by the MEDIEVAL (MultiMEDia transport
*      for mobIlE Video AppLications) project, which is a
*      medium-scale focused research project (STREP) of the 7th
*      Framework Programme (FP7)
*
* Subsequent integration in LENA and extension done by:
*      Marco Miozzo <marco.miozzo@cttc.es>
*/ 


#include <list>
#include <vector>
#include <ns3/log.h>
#include <ns3/pointer.h>
#include <stdint.h>
#include <cmath>
#include <stdint.h>
#include "stdlib.h"
#include <ns3/lte-mi-error-model.h>



namespace ns3 {

NS_LOG_COMPONENT_DEFINE ("LteMiErrorModel");

  // global table of the effective code rates (ECR)s that have BLER performance curves
  static const double BlerCurvesEcrMap[38] = {
    // QPSK (M=2)
    0.01, 0.026, 0.04,   // ECRs of MCS0 retx
    0.08, 0.1, 0.11, 0.15, 0.19, 0.24, 0.3, 0.37, 0.44, 0.51, // ECRs of MCSs
    // 16QAM (M=4)
    0.075, 0.1, 0.15, // ECRs of MCS10 retx
    0.3, 0.33, 0.37, 0.42, 0.48, 0.54, 0.6,// ECRs of MCSs
    // 64QAM (M=6)
    0.1075, 0.143, 0.215,// ECRs of MCS17 retx
    0.43, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.89, 0.92// ECRs of MCSs
  };

  // Table codifing standard MCSs ECR to available ECRs
  static const uint8_t McsEcrBlerTableMapping[29] = {
    3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
    16, 17, 18, 19, 20, 21, 22,
    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37    
  };

  // Table of ECR of the standard MCSs
  static const double McsEcrTable [29] = {0.08, 0.1, 0.11, 0.15, 0.19, 0.24, 0.3, 0.37, 0.44, 0.51, 0.3, 0.33, 0.37, 0.42, 0.48, 0.54, 0.6, 0.43, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.89, 0.92
  };

#if 0 // currently unused
  // Table with ECRs obtained with retransmissions with BLER curves
  static const double HarqRetxEcr[9] = {0.00064, 0.000512, 0.000041, 0.09, 0.027, 0.0081, 0.185, 0.079, 0.034
  };
#endif
 
  // PCFICH-PDCCH Error model based on 3GPP R4-081920 "LTE PDCCH/PCFICH
  //  Demodulation Performance Results with Implementation Margin"
  
  static const double PdcchPcfichBlerCurveXaxis[PDCCH_PCFICH_CURVE_SIZE] = {
      -10,-9.8,-9.6, -9.4, -9.2, -9.0, -8.8, -8.6, -8.4, -8.2, -8.0,
      -7.8, -7.6, -7.4, -7.2, -7.0, -6.8, -6.6, -6.4,   -6.2, -6.0, 
      -5.8, -5.6, -5.4, -5.2, -5.0, -4.8, -4.6, -4.4, -4.2, -4.0, 
      -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, 
      -1.8, -1.6, -1.4, -1.2, -1.0
  };
  
  static const double PdcchPcfichBlerCurveYaxis[PDCCH_PCFICH_CURVE_SIZE] = {
    0.922602, 0.871559, 0.82334, 0.777789, 0.734758, 0.694107, 0.655706,
    0.619429, 0.585159, 0.552785, 0.520927, 0.479229, 0.440869, 0.405579,
    0.373114, 0.343104, 0.309947,0.279994, 0.252936, 0.228492, 0.206048,
    0.181449, 0.159787, 0.140711, 0.123912, 0.109119, 0.0916184, 0.0769244,
    0.0645871, 0.0542285, 0.0454971, 0.037584, 0.0310472, 0.0256473, 
    0.0211866, 0.0175023, 0.0144636, 0.0119524, 0.00987724, 0.00816236,
    0.00673821, 0.00532283, 0.00420476, 0.00332154, 0.00262385, 0.0020727
  
  };
  
#if 0 // currently unused
  static const int TbsIndex[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, -1};
#endif
  
  static const uint16_t cbSizeTable[188] = {   // as K column of table 5.1.3-3 of TS 36,212
    
    40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152,
    160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256, 264,
    272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376,
    384, 392, 400, 408, 416, 424, 432, 440, 448, 456, 464, 472, 480, 488,
    496, 504, 512, 528, 544, 560, 576, 592, 608, 624, 640, 656, 672, 688,
    704, 720, 736, 752, 768, 784, 800, 816, 832, 848, 864, 880, 896, 912,
    928, 944, 960, 976, 992, 1008, 1024, 1056, 1088, 1120, 1152, 1184, 1216,
    1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, 1504, 1536, 1568, 1600,
    1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, 1888, 1920, 1952, 1984,
    2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624, 2688,    2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328, 3392, 3456,
    3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968, 4032, 4096, 4160, 4224,    4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736, 4800, 4864, 4928, 4992,    5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504, 5568, 5632, 5696, 5760,
    5824, 5888, 5952, 6016, 6080, 6144   
  };
  
static const uint16_t cbMiSizeTable [9] = {40, 104, 160, 256, 512, 1024, 2560, 4032, 6144};


static const double MI_map_qpsk[MI_MAP_QPSK_SIZE] = {
  0.008922, 0.011813, 0.014697, 0.017570, 0.020430, 0.023276, 0.026109, 0.028929, 0.031734, 0.034526, 0.037304, 0.040069, 0.042821, 0.045559, 0.048285, 0.050999, 0.053700, 0.056389, 0.059066, 0.061731, 0.064384, 0.067026, 0.069657, 0.072277, 0.074885, 0.077483, 0.080070, 0.082647, 0.085213, 0.087769, 0.090315, 0.092850, 0.095376, 0.097892, 0.100399, 0.102895, 0.105383, 0.107861, 0.110329, 0.112789, 0.115239, 0.117680, 0.120113, 0.122536, 0.124951, 0.127357, 0.129755, 0.132144, 0.134525, 0.136897, 0.139261, 0.141616, 0.143964, 0.146303, 0.148635, 0.150958, 0.153273, 0.155581, 0.157881, 0.160173, 0.162457, 0.164734, 0.167003, 0.169265, 0.171519, 0.173765, 0.176005, 0.178237, 0.180461, 0.182679, 0.184889, 0.187092, 0.189288, 0.191477, 0.193659, 0.195834, 0.198002, 0.200164, 0.202318, 0.204465, 0.206606, 0.208740, 0.210867, 0.212988, 0.215102, 0.217209, 0.219310, 0.221405, 0.223492, 0.225574, 0.227649, 0.229717, 0.231780, 0.233835, 0.235885, 0.237928, 0.239965, 0.241996, 0.244021, 0.246039, 0.248052, 0.250058, 0.252058, 0.254052, 0.256040, 0.258023, 0.259999, 0.261969, 0.263933, 0.265892, 0.267844, 0.269791, 0.271732, 0.273667, 0.275597, 0.277520, 0.279438, 0.281350, 0.283257, 0.285158, 0.287053, 0.288943, 0.290827, 0.292705, 0.294578, 0.296446, 0.298308, 0.300164, 0.302015, 0.303861, 0.305701, 0.307536, 0.309365, 0.311189, 0.313007, 0.314821, 0.316629, 0.318431, 0.320229, 0.322021, 0.323808, 0.325589, 0.327366, 0.329137, 0.330903, 0.332664, 0.334420, 0.336171, 0.337916, 0.339657, 0.341392, 0.343123, 0.344848, 0.346568, 0.348284, 0.349994, 0.351699, 0.353400, 0.355095, 0.356786, 0.358471, 0.360152, 0.361828, 0.363499, 0.365165, 0.366174, 0.367827, 0.369475, 0.371118, 0.372755, 0.374388, 0.376015, 0.377637, 0.379255, 0.380867, 0.382474, 0.384076, 0.385674, 0.387266, 0.388854, 0.390436, 0.392014, 0.393587, 0.395155, 0.396718, 0.398277, 0.399830, 0.401379, 0.402924, 0.404463, 0.405998, 0.407529, 0.409054, 0.410576, 0.412092, 0.413604, 0.415111, 0.416614, 0.418113, 0.419606, 0.421096, 0.422581, 0.424061, 0.425537, 0.427009, 0.428476, 0.429939, 0.431398, 0.432852, 0.434302, 0.435748, 0.437189, 0.438627, 0.440060, 0.441488, 0.442913, 0.444333, 0.445749, 0.447161, 0.448569, 0.449973, 0.451373, 0.452768, 0.454160, 0.455547, 0.456931, 0.458310, 0.459685, 0.461057, 0.462424, 0.463788, 0.465147, 0.466503, 0.467854, 0.469202, 0.470546, 0.471886, 0.473222, 0.474555, 0.475883, 0.477208, 0.478529, 0.479846, 0.481159, 0.482469, 0.483774, 0.485077, 0.486375, 0.487670, 0.488961, 0.490248, 0.491532, 0.492812, 0.494088, 0.495361, 0.496630, 0.497896, 0.499158, 0.500416, 0.501671, 0.502922, 0.504170, 0.505414, 0.506655, 0.507893, 0.509126, 0.510357, 0.511584, 0.512807, 0.514027, 0.515244, 0.516457, 0.517667, 0.518873, 0.520076, 0.521276, 0.522472, 0.523665, 0.524855, 0.526042, 0.527225, 0.528404, 0.529581, 0.530754, 0.531924, 0.533091, 0.534255, 0.535415, 0.536572, 0.537726, 0.538877, 0.540024, 0.541169, 0.542310, 0.543448, 0.544583, 0.545715, 0.546844, 0.547969, 0.549092, 0.550211, 0.551328, 0.552441, 0.553551, 0.554658, 0.555763, 0.556864, 0.557962, 0.559057, 0.560149, 0.561238, 0.562325, 0.563408, 0.564488, 0.565566, 0.566640, 0.567712, 0.568780, 0.569846, 0.570909, 0.571969, 0.573026, 0.574080, 0.575131, 0.576180, 0.577225, 0.578268, 0.579308, 0.580345, 0.581380, 0.582411, 0.583440, 0.584466, 0.585489, 0.586510, 0.587528, 0.588543, 0.589555, 0.590565, 0.591571, 0.592576, 0.593577, 0.594576, 0.595572, 0.596565, 0.597556, 0.598544, 0.599530, 0.600513, 0.601493, 0.602470, 0.603445, 0.604418, 0.605387, 0.606355, 0.607319, 0.608281, 0.609241, 0.610198, 0.611152, 0.612104, 0.613053, 0.614000, 0.614944, 0.615886, 0.616825, 0.617762, 0.618696, 0.619628, 0.620557, 0.621484, 0.622409, 0.623331, 0.624250, 0.625167, 0.626082, 0.626994, 0.627904, 0.628812, 0.629717, 0.630619, 0.631520, 0.632418, 0.633313, 0.634206, 0.635097, 0.635986, 0.636872, 0.637756, 0.638637, 0.639516, 0.640393, 0.641268, 0.642140, 0.643010, 0.643878, 0.644743, 0.645606, 0.646467, 0.647326, 0.648182, 0.649037, 0.649889, 0.650738, 0.651586, 0.652431, 0.653274, 0.654115, 0.654954, 0.655790, 0.656624, 0.657457, 0.658287, 0.659114, 0.659940, 0.660763, 0.661585, 0.662404, 0.663221, 0.664036, 0.664849, 0.665660, 0.666468, 0.667275, 0.668079, 0.668882, 0.669682, 0.670480, 0.671276, 0.672070, 0.672862, 0.673652, 0.674440, 0.675226, 0.676010, 0.676792, 0.677572, 0.678349, 0.679125, 0.679899, 0.680671, 0.681440, 0.682208, 0.682974, 0.683738, 0.684500, 0.685260, 0.686018, 0.686774, 0.687528, 0.688280, 0.689030, 0.689778, 0.690525, 0.691269, 0.692012, 0.692752, 0.693491, 0.694228, 0.694963, 0.695696, 0.696427, 0.697156, 0.697883, 0.698609, 0.699333, 0.700055, 0.700774, 0.701493, 0.702209, 0.702923, 0.703636, 0.704347, 0.705056, 0.705763, 0.706468, 0.707172, 0.707874, 0.708574, 0.709272, 0.709969, 0.710663, 0.711356, 0.712047, 0.712737, 0.713424, 0.714110, 0.714794, 0.715477, 0.716157, 0.716836, 0.717513, 0.718189, 0.718862, 0.719535, 0.720205, 0.720873, 0.721540, 0.722206, 0.722869, 0.723531, 0.724191, 0.724850, 0.725507, 0.726162, 0.726815, 0.727467, 0.728117, 0.728766, 0.729413, 0.730058, 0.730702, 0.731344, 0.731984, 0.732623, 0.733260, 0.733896, 0.734530, 0.735162, 0.735793, 0.736422, 0.737050, 0.737676, 0.738300, 0.738923, 0.739544, 0.740164, 0.740782, 0.741399, 0.742014, 0.742627, 0.743239, 0.743850, 0.744459, 0.745066, 0.745672, 0.746276, 0.746879, 0.747480, 0.748080, 0.748678, 0.749275, 0.749870, 0.750464, 0.751056, 0.751647, 0.752236, 0.752824, 0.753410, 0.753995, 0.754579, 0.755161, 0.755741, 0.756320, 0.756898, 0.757474, 0.758049, 0.758622, 0.759194, 0.759764, 0.760333, 0.760901, 0.761467, 0.762032, 0.762595, 0.763157, 0.763717, 0.764277, 0.764834, 0.765391, 0.765946, 0.766499, 0.767051, 0.767602, 0.768152, 0.768700, 0.769246, 0.769792, 0.770336, 0.770878, 0.771419, 0.771959, 0.772498, 0.773035, 0.773571, 0.774106, 0.774639, 0.775171, 0.775701, 0.776231, 0.776759, 0.777285, 0.777811, 0.778335, 0.778858, 0.779379, 0.779899, 0.780418, 0.780936, 0.781452, 0.781967, 0.782481, 0.782993, 0.783504, 0.784014, 0.784523, 0.785030, 0.785536, 0.786041, 0.786545, 0.787047, 0.787549, 0.788048, 0.788547, 0.789045, 0.789541, 0.790036, 0.790530, 0.791022, 0.791513, 0.792004, 0.792493, 0.792980, 0.793467, 0.793952, 0.794436, 0.794919, 0.795401, 0.795881, 0.796361, 0.796839, 0.797316, 0.797792, 0.798266, 0.798740, 0.799212, 0.799683, 0.800153, 0.800622, 0.801090, 0.801556, 0.802022, 0.802486, 0.802949, 0.803411, 0.803872, 0.804331, 0.804790, 0.805247, 0.805704, 0.806159, 0.806613, 0.807066, 0.807518, 0.807969, 0.808418, 0.808867, 0.809314, 0.809761, 0.810206, 0.810650, 0.811093, 0.811535, 0.811976, 0.812416, 0.812854, 0.813292, 0.813729, 0.814164, 0.814599, 0.815032, 0.815464, 0.815896, 0.816326, 0.816755, 0.817183, 0.817610, 0.818036, 0.818461, 0.818885, 0.819308, 0.819730, 0.820151, 0.820571, 0.820990, 0.821407, 0.821824, 0.822240, 0.822655, 0.823068, 0.823481, 0.823893, 0.824303, 0.824713, 0.825122, 0.825529, 0.825936, 0.826342, 0.826747, 0.827150, 0.827553, 0.827955, 0.828356, 0.828756, 0.829154, 0.829552, 0.829949, 0.830345, 0.830740, 0.831134, 0.831527, 0.831919, 0.832311, 0.832701, 0.833090, 0.833478, 0.833866, 0.834252, 0.834638, 0.835022, 0.835406, 0.835789, 0.836170, 0.836551, 0.836931, 0.837310, 0.837688, 0.838065, 0.838442, 0.838817, 0.839191, 0.839565, 0.839938, 0.840309, 0.840680, 0.841050, 0.841419, 0.841787, 0.842154, 0.842521, 0.842886, 0.843251, 0.843615, 0.843977, 0.844339, 0.844700, 0.845061, 0.845420, 0.845778, 0.846136, 0.846493, 0.846849, 0.847204, 0.847558, 0.847911, 0.848263, 0.848615, 0.848966, 0.849316, 0.849665, 0.850013, 0.850360, 0.850707, 0.851052, 0.851397, 0.851741, 0.852085, 0.852427, 0.852768, 0.853109, 0.853449, 0.853788, 0.854126, 0.854464, 0.854801, 0.855136, 0.855471, 0.855806, 0.856139, 0.856472, 0.856803, 0.857134, 0.857465, 0.857794, 0.858123, 0.858451, 0.858778, 0.859104, 0.859429, 0.859754, 0.860078, 0.860401, 0.860723, 0.861045, 0.861366, 0.861686, 0.862005
};



static const double MI_map_qpsk_axis[MI_MAP_QPSK_SIZE] = {
  0.013000, 0.017000, 0.021000, 0.025000, 0.029000, 0.033000, 0.037000, 0.041000, 0.045000, 0.049000, 0.053000, 0.057000, 0.061000, 0.065000, 0.069000, 0.073000, 0.077000, 0.081000, 0.085000, 0.089000, 0.093000, 0.097000, 0.101000, 0.105000, 0.109000, 0.113000, 0.117000, 0.121000, 0.125000, 0.129000, 0.133000, 0.137000, 0.141000, 0.145000, 0.149000, 0.153000, 0.157000, 0.161000, 0.165000, 0.169000, 0.173000, 0.177000, 0.181000, 0.185000, 0.189000, 0.193000, 0.197000, 0.201000, 0.205000, 0.209000, 0.213000, 0.217000, 0.221000, 0.225000, 0.229000, 0.233000, 0.237000, 0.241000, 0.245000, 0.249000, 0.253000, 0.257000, 0.261000, 0.265000, 0.269000, 0.273000, 0.277000, 0.281000, 0.285000, 0.289000, 0.293000, 0.297000, 0.301000, 0.305000, 0.309000, 0.313000, 0.317000, 0.321000, 0.325000, 0.329000, 0.333000, 0.337000, 0.341000, 0.345000, 0.349000, 0.353000, 0.357000, 0.361000, 0.365000, 0.369000, 0.373000, 0.377000, 0.381000, 0.385000, 0.389000, 0.393000, 0.397000, 0.401000, 0.405000, 0.409000, 0.413000, 0.417000, 0.421000, 0.425000, 0.429000, 0.433000, 0.437000, 0.441000, 0.445000, 0.449000, 0.453000, 0.457000, 0.461000, 0.465000, 0.469000, 0.473000, 0.477000, 0.481000, 0.485000, 0.489000, 0.493000, 0.497000, 0.501000, 0.505000, 0.509000, 0.513000, 0.517000, 0.521000, 0.525000, 0.529000, 0.533000, 0.537000, 0.541000, 0.545000, 0.549000, 0.553000, 0.557000, 0.561000, 0.565000, 0.569000, 0.573000, 0.577000, 0.581000, 0.585000, 0.589000, 0.593000, 0.597000, 0.601000, 0.605000, 0.609000, 0.613000, 0.617000, 0.621000, 0.625000, 0.629000, 0.633000, 0.637000, 0.641000, 0.645000, 0.649000, 0.653000, 0.657000, 0.661000, 0.665000, 0.669000, 0.673000, 0.677000, 0.681000, 0.685000, 0.689000, 0.693000, 0.697000, 0.701000, 0.705000, 0.709000, 0.713000, 0.717000, 0.721000, 0.725000, 0.729000, 0.733000, 0.737000, 0.741000, 0.745000, 0.749000, 0.753000, 0.757000, 0.761000, 0.765000, 0.769000, 0.773000, 0.777000, 0.781000, 0.785000, 0.789000, 0.793000, 0.797000, 0.801000, 0.805000, 0.809000, 0.813000, 0.817000, 0.821000, 0.825000, 0.829000, 0.833000, 0.837000, 0.841000, 0.845000, 0.849000, 0.853000, 0.857000, 0.861000, 0.865000, 0.869000, 0.873000, 0.877000, 0.881000, 0.885000, 0.889000, 0.893000, 0.897000, 0.901000, 0.905000, 0.909000, 0.913000, 0.917000, 0.921000, 0.925000, 0.929000, 0.933000, 0.937000, 0.941000, 0.945000, 0.949000, 0.953000, 0.957000, 0.961000, 0.965000, 0.969000, 0.973000, 0.977000, 0.981000, 0.985000, 0.989000, 0.993000, 0.997000, 1.001000, 1.005000, 1.009000, 1.013000, 1.017000, 1.021000, 1.025000, 1.029000, 1.033000, 1.037000, 1.041000, 1.045000, 1.049000, 1.053000, 1.057000, 1.061000, 1.065000, 1.069000, 1.073000, 1.077000, 1.081000, 1.085000, 1.089000, 1.093000, 1.097000, 1.101000, 1.105000, 1.109000, 1.113000, 1.117000, 1.121000, 1.125000, 1.129000, 1.133000, 1.137000, 1.141000, 1.145000, 1.149000, 1.153000, 1.157000, 1.161000, 1.165000, 1.169000, 1.173000, 1.177000, 1.181000, 1.185000, 1.189000, 1.193000, 1.197000, 1.201000, 1.205000, 1.209000, 1.213000, 1.217000, 1.221000, 1.225000, 1.229000, 1.233000, 1.237000, 1.241000, 1.245000, 1.249000, 1.253000, 1.257000, 1.261000, 1.265000, 1.269000, 1.273000, 1.277000, 1.281000, 1.285000, 1.289000, 1.293000, 1.297000, 1.301000, 1.305000, 1.309000, 1.313000, 1.317000, 1.321000, 1.325000, 1.329000, 1.333000, 1.337000, 1.341000, 1.345000, 1.349000, 1.353000, 1.357000, 1.361000, 1.365000, 1.369000, 1.373000, 1.377000, 1.381000, 1.385000, 1.389000, 1.393000, 1.397000, 1.401000, 1.405000, 1.409000, 1.413000, 1.417000, 1.421000, 1.425000, 1.429000, 1.433000, 1.437000, 1.441000, 1.445000, 1.449000, 1.453000, 1.457000, 1.461000, 1.465000, 1.469000, 1.473000, 1.477000, 1.481000, 1.485000, 1.489000, 1.493000, 1.497000, 1.501000, 1.505000, 1.509000, 1.513000, 1.517000, 1.521000, 1.525000, 1.529000, 1.533000, 1.537000, 1.541000, 1.545000, 1.549000, 1.553000, 1.557000, 1.561000, 1.565000, 1.569000, 1.573000, 1.577000, 1.581000, 1.585000, 1.589000, 1.593000, 1.597000, 1.601000, 1.605000, 1.609000, 1.613000, 1.617000, 1.621000, 1.625000, 1.629000, 1.633000, 1.637000, 1.641000, 1.645000, 1.649000, 1.653000, 1.657000, 1.661000, 1.665000, 1.669000, 1.673000, 1.677000, 1.681000, 1.685000, 1.689000, 1.693000, 1.697000, 1.701000, 1.705000, 1.709000, 1.713000, 1.717000, 1.721000, 1.725000, 1.729000, 1.733000, 1.737000, 1.741000, 1.745000, 1.749000, 1.753000, 1.757000, 1.761000, 1.765000, 1.769000, 1.773000, 1.777000, 1.781000, 1.785000, 1.789000, 1.793000, 1.797000, 1.801000, 1.805000, 1.809000, 1.813000, 1.817000, 1.821000, 1.825000, 1.829000, 1.833000, 1.837000, 1.841000, 1.845000, 1.849000, 1.853000, 1.857000, 1.861000, 1.865000, 1.869000, 1.873000, 1.877000, 1.881000, 1.885000, 1.889000, 1.893000, 1.897000, 1.901000, 1.905000, 1.909000, 1.913000, 1.917000, 1.921000, 1.925000, 1.929000, 1.933000, 1.937000, 1.941000, 1.945000, 1.949000, 1.953000, 1.957000, 1.961000, 1.965000, 1.969000, 1.973000, 1.977000, 1.981000, 1.985000, 1.989000, 1.993000, 1.997000, 2.001000, 2.005000, 2.009000, 2.013000, 2.017000, 2.021000, 2.025000, 2.029000, 2.033000, 2.037000, 2.041000, 2.045000, 2.049000, 2.053000, 2.057000, 2.061000, 2.065000, 2.069000, 2.073000, 2.077000, 2.081000, 2.085000, 2.089000, 2.093000, 2.097000, 2.101000, 2.105000, 2.109000, 2.113000, 2.117000, 2.121000, 2.125000, 2.129000, 2.133000, 2.137000, 2.141000, 2.145000, 2.149000, 2.153000, 2.157000, 2.161000, 2.165000, 2.169000, 2.173000, 2.177000, 2.181000, 2.185000, 2.189000, 2.193000, 2.197000, 2.201000, 2.205000, 2.209000, 2.213000, 2.217000, 2.221000, 2.225000, 2.229000, 2.233000, 2.237000, 2.241000, 2.245000, 2.249000, 2.253000, 2.257000, 2.261000, 2.265000, 2.269000, 2.273000, 2.277000, 2.281000, 2.285000, 2.289000, 2.293000, 2.297000, 2.301000, 2.305000, 2.309000, 2.313000, 2.317000, 2.321000, 2.325000, 2.329000, 2.333000, 2.337000, 2.341000, 2.345000, 2.349000, 2.353000, 2.357000, 2.361000, 2.365000, 2.369000, 2.373000, 2.377000, 2.381000, 2.385000, 2.389000, 2.393000, 2.397000, 2.401000, 2.405000, 2.409000, 2.413000, 2.417000, 2.421000, 2.425000, 2.429000, 2.433000, 2.437000, 2.441000, 2.445000, 2.449000, 2.453000, 2.457000, 2.461000, 2.465000, 2.469000, 2.473000, 2.477000, 2.481000, 2.485000, 2.489000, 2.493000, 2.497000, 2.501000, 2.505000, 2.509000, 2.513000, 2.517000, 2.521000, 2.525000, 2.529000, 2.533000, 2.537000, 2.541000, 2.545000, 2.549000, 2.553000, 2.557000, 2.561000, 2.565000, 2.569000, 2.573000, 2.577000, 2.581000, 2.585000, 2.589000, 2.593000, 2.597000, 2.601000, 2.605000, 2.609000, 2.613000, 2.617000, 2.621000, 2.625000, 2.629000, 2.633000, 2.637000, 2.641000, 2.645000, 2.649000, 2.653000, 2.657000, 2.661000, 2.665000, 2.669000, 2.673000, 2.677000, 2.681000, 2.685000, 2.689000, 2.693000, 2.697000, 2.701000, 2.705000, 2.709000, 2.713000, 2.717000, 2.721000, 2.725000, 2.729000, 2.733000, 2.737000, 2.741000, 2.745000, 2.749000, 2.753000, 2.757000, 2.761000, 2.765000, 2.769000, 2.773000, 2.777000, 2.781000, 2.785000, 2.789000, 2.793000, 2.797000, 2.801000, 2.805000, 2.809000, 2.813000, 2.817000, 2.821000, 2.825000, 2.829000, 2.833000, 2.837000, 2.841000, 2.845000, 2.849000, 2.853000, 2.857000, 2.861000, 2.865000, 2.869000, 2.873000, 2.877000, 2.881000, 2.885000, 2.889000, 2.893000, 2.897000, 2.901000, 2.905000, 2.909000, 2.913000, 2.917000, 2.921000, 2.925000, 2.929000, 2.933000, 2.937000, 2.941000, 2.945000, 2.949000, 2.953000, 2.957000, 2.961000, 2.965000, 2.969000, 2.973000, 2.977000, 2.981000, 2.985000, 2.989000, 2.993000, 2.997000, 3.001000, 3.005000, 3.009000, 3.013000, 3.017000, 3.021000, 3.025000, 3.029000, 3.033000, 3.037000, 3.041000, 3.045000, 3.049000, 3.053000, 3.057000, 3.061000, 3.065000, 3.069000, 3.073000, 3.077000, 3.081000, 3.085000, 3.089000, 3.093000, 3.097000, 3.101000, 3.105000, 3.109000, 3.113000, 3.117000, 3.121000, 3.125000, 3.129000, 3.133000, 3.137000, 3.141000, 3.145000, 3.149000, 3.153000, 3.157000, 3.161000, 3.165000, 3.169000, 3.173000, 3.177000, 3.181000, 3.185000, 3.189000, 3.193000, 3.197000
};


static const double MI_map_16qam[MI_MAP_16QAM_SIZE] = {
  0.018884, 0.021859, 0.024808, 0.027732, 0.030631, 0.033506, 0.036357, 0.039185, 0.041991, 0.044776, 0.047538, 0.050280, 0.053002, 0.055703, 0.058385, 0.061048, 0.063692, 0.066318, 0.068925, 0.071514, 0.074086, 0.076640, 0.079178, 0.081699, 0.084203, 0.086691, 0.089163, 0.091619, 0.094059, 0.096484, 0.098894, 0.101289, 0.103669, 0.106034, 0.108385, 0.110721, 0.113043, 0.115351, 0.117645, 0.119926, 0.122192, 0.124446, 0.126686, 0.128912, 0.131126, 0.133326, 0.135514, 0.137689, 0.139852, 0.142001, 0.144139, 0.146101, 0.148211, 0.150308, 0.152392, 0.154464, 0.156524, 0.158571, 0.160606, 0.162630, 0.164641, 0.166641, 0.168629, 0.170606, 0.172572, 0.174526, 0.176470, 0.178403, 0.180325, 0.182236, 0.184136, 0.186027, 0.187907, 0.189777, 0.191636, 0.193486, 0.195326, 0.197156, 0.198976, 0.200787, 0.202588, 0.204380, 0.206162, 0.207935, 0.209700, 0.211455, 0.213201, 0.214938, 0.216666, 0.218386, 0.220097, 0.221800, 0.223494, 0.225180, 0.226857, 0.228526, 0.230187, 0.231840, 0.233485, 0.235121, 0.236750, 0.238372, 0.239985, 0.241591, 0.243189, 0.244779, 0.246362, 0.247938, 0.249506, 0.251067, 0.252621, 0.254167, 0.255707, 0.257239, 0.258764, 0.260283, 0.261794, 0.263299, 0.264797, 0.266288, 0.267772, 0.269250, 0.270722, 0.272186, 0.273645, 0.275097, 0.276542, 0.277981, 0.279414, 0.280841, 0.282262, 0.283676, 0.285085, 0.286487, 0.287883, 0.289274, 0.290659, 0.292037, 0.293410, 0.294777, 0.296139, 0.297495, 0.298845, 0.300189, 0.301528, 0.302862, 0.304190, 0.305513, 0.306830, 0.308142, 0.309449, 0.310750, 0.312046, 0.313337, 0.314623, 0.315903, 0.317179, 0.318449, 0.319715, 0.320975, 0.322231, 0.323481, 0.324727, 0.325968, 0.327204, 0.328436, 0.329662, 0.330884, 0.332102, 0.333314, 0.334522, 0.335726, 0.336924, 0.338119, 0.339309, 0.340494, 0.341675, 0.342852, 0.344024, 0.345192, 0.346355, 0.347515, 0.348670, 0.349821, 0.350967, 0.352110, 0.353248, 0.354382, 0.355512, 0.356639, 0.357761, 0.358879, 0.359993, 0.361103, 0.362209, 0.363311, 0.364410, 0.365504, 0.366595, 0.367682, 0.368765, 0.369844, 0.370920, 0.371992, 0.373060, 0.374125, 0.375186, 0.376243, 0.377297, 0.378347, 0.379393, 0.380436, 0.381476, 0.382512, 0.383545, 0.384574, 0.385600, 0.386622, 0.387641, 0.388657, 0.389669, 0.390678, 0.391683, 0.392686, 0.393685, 0.394681, 0.395674, 0.396663, 0.397649, 0.398632, 0.399612, 0.400589, 0.401563, 0.402534, 0.403501, 0.404466, 0.405427, 0.406386, 0.407341, 0.408294, 0.409243, 0.410190, 0.411133, 0.412074, 0.413012, 0.413947, 0.414879, 0.415808, 0.416735, 0.417658, 0.418579, 0.419497, 0.420412, 0.421325, 0.422234, 0.423142, 0.424046, 0.424947, 0.425846, 0.426743, 0.427636, 0.428527, 0.429416, 0.430302, 0.431185, 0.432065, 0.432943, 0.433819, 0.434692, 0.435562, 0.436430, 0.437296, 0.438159, 0.439019, 0.439877, 0.440733, 0.441586, 0.442437, 0.443285, 0.444131, 0.444975, 0.445816, 0.446493, 0.447329, 0.448163, 0.448994, 0.449823, 0.450650, 0.451474, 0.452297, 0.453116, 0.453934, 0.454749, 0.455562, 0.456373, 0.457182, 0.457988, 0.458793, 0.459595, 0.460395, 0.461192, 0.461988, 0.462781, 0.463572, 0.464362, 0.465149, 0.465934, 0.466716, 0.467497, 0.468276, 0.469053, 0.469827, 0.470600, 0.471370, 0.472139, 0.472905, 0.473670, 0.474432, 0.475193, 0.475952, 0.476708, 0.477463, 0.478216, 0.478967, 0.479716, 0.480463, 0.481208, 0.481951, 0.482692, 0.483432, 0.484169, 0.484905, 0.485639, 0.486371, 0.487101, 0.487830, 0.488556, 0.489281, 0.490004, 0.490726, 0.491445, 0.492163, 0.492879, 0.493593, 0.494306, 0.495016, 0.495725, 0.496433, 0.497138, 0.497842, 0.498544, 0.499245, 0.499944, 0.500641, 0.501337, 0.502030, 0.502723, 0.503413, 0.504102, 0.504790, 0.505475, 0.506159, 0.506842, 0.507523, 0.508202, 0.508880, 0.509556, 0.510231, 0.510904, 0.511575, 0.512245, 0.512914, 0.513581, 0.514246, 0.514910, 0.515572, 0.516233, 0.516893, 0.517551, 0.518207, 0.518862, 0.519515, 0.520167, 0.520818, 0.521467, 0.522115, 0.522761, 0.523405, 0.524049, 0.524691, 0.525331, 0.525970, 0.526608, 0.527244, 0.527879, 0.528513, 0.529145, 0.529776, 0.530405, 0.531033, 0.531660, 0.532285, 0.532909, 0.533532, 0.534153, 0.534773, 0.535392, 0.536009, 0.536625, 0.537240, 0.537853, 0.538465, 0.539076, 0.539361, 0.539968, 0.540575, 0.541180, 0.541783, 0.542386, 0.542987, 0.543587, 0.544186, 0.544783, 0.545379, 0.545974, 0.546568, 0.547160, 0.547751, 0.548341, 0.548930, 0.549517, 0.550103, 0.550688, 0.551272, 0.551855, 0.552436, 0.553016, 0.553595, 0.554173, 0.554749, 0.555325, 0.555899, 0.556472, 0.557044, 0.557615, 0.558184, 0.558753, 0.559320, 0.559886, 0.560451, 0.561015, 0.561578, 0.562140, 0.562700, 0.563259, 0.563818, 0.564375, 0.564931, 0.565486, 0.566040, 0.566593, 0.567144, 0.567695, 0.568244, 0.568793, 0.569340, 0.569887, 0.570432, 0.570976, 0.571519, 0.572061, 0.572602, 0.573142, 0.573681, 0.574219, 0.574756, 0.575292, 0.575827, 0.576361, 0.576894, 0.577425, 0.577956, 0.578486, 0.579015, 0.579543, 0.580069, 0.580595, 0.581120, 0.581644, 0.582167, 0.582689, 0.583210, 0.583730, 0.584249, 0.584767, 0.585284, 0.585800, 0.586315, 0.586829, 0.587342, 0.587855, 0.588366, 0.588877, 0.589386, 0.589895, 0.590402, 0.590909, 0.591415, 0.591920, 0.592424, 0.592927, 0.593429, 0.593930, 0.594431, 0.594930, 0.595429, 0.595926, 0.596423, 0.596919, 0.597414, 0.597908, 0.598402, 0.598894, 0.599386, 0.599876, 0.600366, 0.600855, 0.601343, 0.601830, 0.602317, 0.602802, 0.603287, 0.603771, 0.604254, 0.604736, 0.605217, 0.605697, 0.606177, 0.606656, 0.607134, 0.607611, 0.608087, 0.608563, 0.609038, 0.609511, 0.609985, 0.610457, 0.610928, 0.611399, 0.611869, 0.612338, 0.612806, 0.613274, 0.613740, 0.614206, 0.614671, 0.615136, 0.615599, 0.616062, 0.616524, 0.616985, 0.617446, 0.617905, 0.618364, 0.618822, 0.619280, 0.619736, 0.620192, 0.620647, 0.621102, 0.621555, 0.622008, 0.622460, 0.622912, 0.623362, 0.623812, 0.624261, 0.624710, 0.625157, 0.625604, 0.626051, 0.626496, 0.626941, 0.627385, 0.627828, 0.628271, 0.628713, 0.629154, 0.629594, 0.630034, 0.630473, 0.630911, 0.631349, 0.631786, 0.632222, 0.632658, 0.633093, 0.633527, 0.633960, 0.634393, 0.634825, 0.635257, 0.635687, 0.636117, 0.636547, 0.636975, 0.637403, 0.637831, 0.638257, 0.638683, 0.639109, 0.639533, 0.639957, 0.640381, 0.640803, 0.641225, 0.641647, 0.642067, 0.642487, 0.642907, 0.643326, 0.643744, 0.644161, 0.644578, 0.644994, 0.645410, 0.645824, 0.646239, 0.646652, 0.647065, 0.647477, 0.647889, 0.648300, 0.648711, 0.649120, 0.649530, 0.649938, 0.650346, 0.650753, 0.651160, 0.651566, 0.651972, 0.652377, 0.652781, 0.653184, 0.653587, 0.653990, 0.654392, 0.654793, 0.655193, 0.655593, 0.655993, 0.656392, 0.656790, 0.657187, 0.657584, 0.657981, 0.658377, 0.658772, 0.659167, 0.659561, 0.659954, 0.660347, 0.660739, 0.661131, 0.661522, 0.661913, 0.662303, 0.662692, 0.663081, 0.663469, 0.663857, 0.664244, 0.664631, 0.665017, 0.665402, 0.665787, 0.666171, 0.666555, 0.666938, 0.667321, 0.667703, 0.668085, 0.668466, 0.668846, 0.669226, 0.669605, 0.669984, 0.670362, 0.670740, 0.671117, 0.671494, 0.671870, 0.672245, 0.672620, 0.672995, 0.673368, 0.673742, 0.674115, 0.674487, 0.674859, 0.675230, 0.675601, 0.675971, 0.676340, 0.676709, 0.677078, 0.677446, 0.677814, 0.678181, 0.678547, 0.678913, 0.679279, 0.679643, 0.680008, 0.680372, 0.680735, 0.681098, 0.681460, 0.681822, 0.682184, 0.682544, 0.682905, 0.683265, 0.683624, 0.683983, 0.684341, 0.684699, 0.685056, 0.685413, 0.685769, 0.686125, 0.686481, 0.686835, 0.687190, 0.687544, 0.687897, 0.688250, 0.688602, 0.688954, 0.689305, 0.689656, 0.690007, 0.690357, 0.690706, 0.691055, 0.691404, 0.691752, 0.692099, 0.692446, 0.692793, 0.693139, 0.693485, 0.693830, 0.694175, 0.694519, 0.694863, 0.695206, 0.695549, 0.695891, 0.696233, 0.696574, 0.696915, 0.697256, 0.697596, 0.697935, 0.698274, 0.698613, 0.698951, 0.699289, 0.699626, 0.699963, 0.700299, 0.700635, 0.700971, 0.701306, 0.701640, 0.701974, 0.702308, 0.702641, 0.702974, 0.703306, 0.703638, 0.703969, 0.704300, 0.704631, 0.704961, 0.705291, 0.705620, 0.705949, 0.706277, 0.706605, 0.706932, 0.707259, 0.707586, 0.707912, 0.708238, 0.708563, 0.708888, 0.709212, 0.709536, 0.709859, 0.710183, 0.710505, 0.710828, 0.711149, 0.711471, 0.711792, 0.712112, 0.712432, 0.712752, 0.713071, 0.713390, 0.713709, 0.714027, 0.714344, 0.714661, 0.714978, 0.715295, 0.715611, 0.715926, 0.716241, 0.716556, 0.716870, 0.717184, 0.717497, 0.717811, 0.718123, 0.718435, 0.718747, 0.719059, 0.719370, 0.719680, 0.719991, 0.720300, 0.720610, 0.720919, 0.721227, 0.721536, 0.721843, 0.722151, 0.722458, 0.722764, 0.723071, 0.723376, 0.723682, 0.723987, 0.724291, 0.724596, 0.724899, 0.725203, 0.725506, 0.725809, 0.726111, 0.726413, 0.726714, 0.727015, 0.727316, 0.727616, 0.727916, 0.728216, 0.728515, 0.728814, 0.729112, 0.729410, 0.729708, 0.730005, 0.730302, 0.730599, 0.730895, 0.731191, 0.731486, 0.731781, 0.732076, 0.732370, 0.732664, 0.732957, 0.733250, 0.733543, 0.733835, 0.734127, 0.734419, 0.734710, 0.735001, 0.735292, 0.735582, 0.735872, 0.736161, 0.736450, 0.736739, 0.737027, 0.737315, 0.737603, 0.737890, 0.738177, 0.738463, 0.738750, 0.739035, 0.739321, 0.739606, 0.739891, 0.740175, 0.740459, 0.740743, 0.741026, 0.741309, 0.741591, 0.741874, 0.742155, 0.742437, 0.742718, 0.742999, 0.743279, 0.743559, 0.743839, 0.744119, 0.744398, 0.744676, 0.744955, 0.745233, 0.745510, 0.745788, 0.746065, 0.746341, 0.746618, 0.746893, 0.747169, 0.747444, 0.747719, 0.747994, 0.748268, 0.748542, 0.748815, 0.749089, 0.749361, 0.749634, 0.749906, 0.750178, 0.750450, 0.750721, 0.750992, 0.751262, 0.751532, 0.751802, 0.752072, 0.752341, 0.752610, 0.752878, 0.753146, 0.753414, 0.753682, 0.753949, 0.754216, 0.754482, 0.754748, 0.755014, 0.755280, 0.755545, 0.755810, 0.756074, 0.756339, 0.756603, 0.756866, 0.757129, 0.757392, 0.757655, 0.757917, 0.758179, 0.758441, 0.758702, 0.758963, 0.759224, 0.759484, 0.759744, 0.760004, 0.760264, 0.760523, 0.760781, 0.761040, 0.761298, 0.761556, 0.761813, 0.762071, 0.762328, 0.762584, 0.762840, 0.763096, 0.763352, 0.763607, 0.763862, 0.764117, 0.764371, 0.764626, 0.764879
};

static const double MI_map_16qam_axis[MI_MAP_16QAM_SIZE] = {
  0.063000, 0.073000, 0.083000, 0.093000, 0.103000, 0.113000, 0.123000, 0.133000, 0.143000, 0.153000, 0.163000, 0.173000, 0.183000, 0.193000, 0.203000, 0.213000, 0.223000, 0.233000, 0.243000, 0.253000, 0.263000, 0.273000, 0.283000, 0.293000, 0.303000, 0.313000, 0.323000, 0.333000, 0.343000, 0.353000, 0.363000, 0.373000, 0.383000, 0.393000, 0.403000, 0.413000, 0.423000, 0.433000, 0.443000, 0.453000, 0.463000, 0.473000, 0.483000, 0.493000, 0.503000, 0.513000, 0.523000, 0.533000, 0.543000, 0.553000, 0.563000, 0.573000, 0.583000, 0.593000, 0.603000, 0.613000, 0.623000, 0.633000, 0.643000, 0.653000, 0.663000, 0.673000, 0.683000, 0.693000, 0.703000, 0.713000, 0.723000, 0.733000, 0.743000, 0.753000, 0.763000, 0.773000, 0.783000, 0.793000, 0.803000, 0.813000, 0.823000, 0.833000, 0.843000, 0.853000, 0.863000, 0.873000, 0.883000, 0.893000, 0.903000, 0.913000, 0.923000, 0.933000, 0.943000, 0.953000, 0.963000, 0.973000, 0.983000, 0.993000, 1.003000, 1.013000, 1.023000, 1.033000, 1.043000, 1.053000, 1.063000, 1.073000, 1.083000, 1.093000, 1.103000, 1.113000, 1.123000, 1.133000, 1.143000, 1.153000, 1.163000, 1.173000, 1.183000, 1.193000, 1.203000, 1.213000, 1.223000, 1.233000, 1.243000, 1.253000, 1.263000, 1.273000, 1.283000, 1.293000, 1.303000, 1.313000, 1.323000, 1.333000, 1.343000, 1.353000, 1.363000, 1.373000, 1.383000, 1.393000, 1.403000, 1.413000, 1.423000, 1.433000, 1.443000, 1.453000, 1.463000, 1.473000, 1.483000, 1.493000, 1.503000, 1.513000, 1.523000, 1.533000, 1.543000, 1.553000, 1.563000, 1.573000, 1.583000, 1.593000, 1.603000, 1.613000, 1.623000, 1.633000, 1.643000, 1.653000, 1.663000, 1.673000, 1.683000, 1.693000, 1.703000, 1.713000, 1.723000, 1.733000, 1.743000, 1.753000, 1.763000, 1.773000, 1.783000, 1.793000, 1.803000, 1.813000, 1.823000, 1.833000, 1.843000, 1.853000, 1.863000, 1.873000, 1.883000, 1.893000, 1.903000, 1.913000, 1.923000, 1.933000, 1.943000, 1.953000, 1.963000, 1.973000, 1.983000, 1.993000, 2.003000, 2.013000, 2.023000, 2.033000, 2.043000, 2.053000, 2.063000, 2.073000, 2.083000, 2.093000, 2.103000, 2.113000, 2.123000, 2.133000, 2.143000, 2.153000, 2.163000, 2.173000, 2.183000, 2.193000, 2.203000, 2.213000, 2.223000, 2.233000, 2.243000, 2.253000, 2.263000, 2.273000, 2.283000, 2.293000, 2.303000, 2.313000, 2.323000, 2.333000, 2.343000, 2.353000, 2.363000, 2.373000, 2.383000, 2.393000, 2.403000, 2.413000, 2.423000, 2.433000, 2.443000, 2.453000, 2.463000, 2.473000, 2.483000, 2.493000, 2.503000, 2.513000, 2.523000, 2.533000, 2.543000, 2.553000, 2.563000, 2.573000, 2.583000, 2.593000, 2.603000, 2.613000, 2.623000, 2.633000, 2.643000, 2.653000, 2.663000, 2.673000, 2.683000, 2.693000, 2.703000, 2.713000, 2.723000, 2.733000, 2.743000, 2.753000, 2.763000, 2.773000, 2.783000, 2.793000, 2.803000, 2.813000, 2.823000, 2.833000, 2.843000, 2.853000, 2.863000, 2.873000, 2.883000, 2.893000, 2.903000, 2.913000, 2.923000, 2.933000, 2.943000, 2.953000, 2.963000, 2.973000, 2.983000, 2.993000, 3.003000, 3.013000, 3.023000, 3.033000, 3.043000, 3.053000, 3.063000, 3.073000, 3.083000, 3.093000, 3.103000, 3.113000, 3.123000, 3.133000, 3.143000, 3.153000, 3.163000, 3.173000, 3.183000, 3.193000, 3.203000, 3.213000, 3.223000, 3.233000, 3.243000, 3.253000, 3.263000, 3.273000, 3.283000, 3.293000, 3.303000, 3.313000, 3.323000, 3.333000, 3.343000, 3.353000, 3.363000, 3.373000, 3.383000, 3.393000, 3.403000, 3.413000, 3.423000, 3.433000, 3.443000, 3.453000, 3.463000, 3.473000, 3.483000, 3.493000, 3.503000, 3.513000, 3.523000, 3.533000, 3.543000, 3.553000, 3.563000, 3.573000, 3.583000, 3.593000, 3.603000, 3.613000, 3.623000, 3.633000, 3.643000, 3.653000, 3.663000, 3.673000, 3.683000, 3.693000, 3.703000, 3.713000, 3.723000, 3.733000, 3.743000, 3.753000, 3.763000, 3.773000, 3.783000, 3.793000, 3.803000, 3.813000, 3.823000, 3.833000, 3.843000, 3.853000, 3.863000, 3.873000, 3.883000, 3.893000, 3.903000, 3.913000, 3.923000, 3.933000, 3.943000, 3.953000, 3.963000, 3.973000, 3.983000, 3.993000, 4.003000, 4.013000, 4.023000, 4.033000, 4.043000, 4.053000, 4.063000, 4.073000, 4.083000, 4.093000, 4.103000, 4.113000, 4.123000, 4.133000, 4.143000, 4.153000, 4.163000, 4.173000, 4.183000, 4.193000, 4.203000, 4.213000, 4.223000, 4.233000, 4.243000, 4.253000, 4.263000, 4.273000, 4.283000, 4.293000, 4.303000, 4.313000, 4.323000, 4.333000, 4.343000, 4.353000, 4.363000, 4.373000, 4.383000, 4.393000, 4.403000, 4.413000, 4.423000, 4.433000, 4.443000, 4.453000, 4.463000, 4.473000, 4.483000, 4.493000, 4.503000, 4.513000, 4.523000, 4.533000, 4.543000, 4.553000, 4.563000, 4.573000, 4.583000, 4.593000, 4.603000, 4.613000, 4.623000, 4.633000, 4.643000, 4.653000, 4.663000, 4.673000, 4.683000, 4.693000, 4.703000, 4.713000, 4.723000, 4.733000, 4.743000, 4.753000, 4.763000, 4.773000, 4.783000, 4.793000, 4.803000, 4.813000, 4.823000, 4.833000, 4.843000, 4.853000, 4.863000, 4.873000, 4.883000, 4.893000, 4.903000, 4.913000, 4.923000, 4.933000, 4.943000, 4.953000, 4.963000, 4.973000, 4.983000, 4.993000, 5.003000, 5.013000, 5.023000, 5.033000, 5.043000, 5.053000, 5.063000, 5.073000, 5.083000, 5.093000, 5.103000, 5.113000, 5.123000, 5.133000, 5.143000, 5.153000, 5.163000, 5.173000, 5.183000, 5.193000, 5.203000, 5.213000, 5.223000, 5.233000, 5.243000, 5.253000, 5.263000, 5.273000, 5.283000, 5.293000, 5.303000, 5.313000, 5.323000, 5.333000, 5.343000, 5.353000, 5.363000, 5.373000, 5.383000, 5.393000, 5.403000, 5.413000, 5.423000, 5.433000, 5.443000, 5.453000, 5.463000, 5.473000, 5.483000, 5.493000, 5.503000, 5.513000, 5.523000, 5.533000, 5.543000, 5.553000, 5.563000, 5.573000, 5.583000, 5.593000, 5.603000, 5.613000, 5.623000, 5.633000, 5.643000, 5.653000, 5.663000, 5.673000, 5.683000, 5.693000, 5.703000, 5.713000, 5.723000, 5.733000, 5.743000, 5.753000, 5.763000, 5.773000, 5.783000, 5.793000, 5.803000, 5.813000, 5.823000, 5.833000, 5.843000, 5.853000, 5.863000, 5.873000, 5.883000, 5.893000, 5.903000, 5.913000, 5.923000, 5.933000, 5.943000, 5.953000, 5.963000, 5.973000, 5.983000, 5.993000, 6.003000, 6.013000, 6.023000, 6.033000, 6.043000, 6.053000, 6.063000, 6.073000, 6.083000, 6.093000, 6.103000, 6.113000, 6.123000, 6.133000, 6.143000, 6.153000, 6.163000, 6.173000, 6.183000, 6.193000, 6.203000, 6.213000, 6.223000, 6.233000, 6.243000, 6.253000, 6.263000, 6.273000, 6.283000, 6.293000, 6.303000, 6.313000, 6.323000, 6.333000, 6.343000, 6.353000, 6.363000, 6.373000, 6.383000, 6.393000, 6.403000, 6.413000, 6.423000, 6.433000, 6.443000, 6.453000, 6.463000, 6.473000, 6.483000, 6.493000, 6.503000, 6.513000, 6.523000, 6.533000, 6.543000, 6.553000, 6.563000, 6.573000, 6.583000, 6.593000, 6.603000, 6.613000, 6.623000, 6.633000, 6.643000, 6.653000, 6.663000, 6.673000, 6.683000, 6.693000, 6.703000, 6.713000, 6.723000, 6.733000, 6.743000, 6.753000, 6.763000, 6.773000, 6.783000, 6.793000, 6.803000, 6.813000, 6.823000, 6.833000, 6.843000, 6.853000, 6.863000, 6.873000, 6.883000, 6.893000, 6.903000, 6.913000, 6.923000, 6.933000, 6.943000, 6.953000, 6.963000, 6.973000, 6.983000, 6.993000, 7.003000, 7.013000, 7.023000, 7.033000, 7.043000, 7.053000, 7.063000, 7.073000, 7.083000, 7.093000, 7.103000, 7.113000, 7.123000, 7.133000, 7.143000, 7.153000, 7.163000, 7.173000, 7.183000, 7.193000, 7.203000, 7.213000, 7.223000, 7.233000, 7.243000, 7.253000, 7.263000, 7.273000, 7.283000, 7.293000, 7.303000, 7.313000, 7.323000, 7.333000, 7.343000, 7.353000, 7.363000, 7.373000, 7.383000, 7.393000, 7.403000, 7.413000, 7.423000, 7.433000, 7.443000, 7.453000, 7.463000, 7.473000, 7.483000, 7.493000, 7.503000, 7.513000, 7.523000, 7.533000, 7.543000, 7.553000, 7.563000, 7.573000, 7.583000, 7.593000, 7.603000, 7.613000, 7.623000, 7.633000, 7.643000, 7.653000, 7.663000, 7.673000, 7.683000, 7.693000, 7.703000, 7.713000, 7.723000, 7.733000, 7.743000, 7.753000, 7.763000, 7.773000, 7.783000, 7.793000, 7.803000, 7.813000, 7.823000, 7.833000, 7.843000, 7.853000, 7.863000, 7.873000, 7.883000, 7.893000, 7.903000, 7.913000, 7.923000, 7.933000, 7.943000, 7.953000, 7.963000, 7.973000, 7.983000, 7.993000, 8.003000, 8.013000, 8.023000, 8.033000, 8.043000, 8.053000, 8.063000, 8.073000, 8.083000, 8.093000, 8.103000, 8.113000, 8.123000, 8.133000, 8.143000, 8.153000, 8.163000, 8.173000, 8.183000, 8.193000, 8.203000, 8.213000, 8.223000, 8.233000, 8.243000, 8.253000, 8.263000, 8.273000, 8.283000, 8.293000, 8.303000, 8.313000, 8.323000, 8.333000, 8.343000, 8.353000, 8.363000, 8.373000, 8.383000, 8.393000, 8.403000, 8.413000, 8.423000, 8.433000, 8.443000, 8.453000, 8.463000, 8.473000, 8.483000, 8.493000, 8.503000, 8.513000, 8.523000, 8.533000, 8.543000, 8.553000, 8.563000, 8.573000, 8.583000, 8.593000, 8.603000, 8.613000, 8.623000, 8.633000, 8.643000, 8.653000, 8.663000, 8.673000, 8.683000, 8.693000, 8.703000, 8.713000, 8.723000, 8.733000, 8.743000, 8.753000, 8.763000, 8.773000, 8.783000, 8.793000, 8.803000, 8.813000, 8.823000, 8.833000, 8.843000, 8.853000, 8.863000, 8.873000, 8.883000, 8.893000, 8.903000, 8.913000, 8.923000, 8.933000, 8.943000, 8.953000, 8.963000, 8.973000, 8.983000, 8.993000, 9.003000, 9.013000, 9.023000, 9.033000, 9.043000, 9.053000, 9.063000, 9.073000, 9.083000, 9.093000, 9.103000, 9.113000, 9.123000, 9.133000, 9.143000, 9.153000, 9.163000, 9.173000, 9.183000, 9.193000, 9.203000, 9.213000, 9.223000, 9.233000, 9.243000, 9.253000, 9.263000, 9.273000, 9.283000, 9.293000, 9.303000, 9.313000, 9.323000, 9.333000, 9.343000, 9.353000, 9.363000, 9.373000, 9.383000, 9.393000, 9.403000, 9.413000, 9.423000, 9.433000, 9.443000, 9.453000, 9.463000, 9.473000, 9.483000, 9.493000, 9.503000, 9.513000, 9.523000, 9.533000, 9.543000, 9.553000, 9.563000, 9.573000, 9.583000, 9.593000, 9.603000, 9.613000, 9.623000, 9.633000, 9.643000, 9.653000, 9.663000, 9.673000, 9.683000, 9.693000, 9.703000, 9.713000, 9.723000, 9.733000, 9.743000, 9.753000, 9.763000, 9.773000, 9.783000, 9.793000, 9.803000, 9.813000, 9.823000, 9.833000, 9.843000, 9.853000, 9.863000, 9.873000, 9.883000, 9.893000, 9.903000, 9.913000, 9.923000, 9.933000, 9.943000, 9.953000, 9.963000, 9.973000, 9.983000, 9.993000
};


static const double MI_map_64qam[MI_MAP_64QAM_SIZE] = {
  0.036455, 0.064415, 0.090225, 0.114215, 0.136597, 0.157298, 0.176808, 0.195063, 0.212193, 0.228310, 0.243505, 0.257860, 0.271445, 0.284323, 0.296550, 0.308175, 0.319243, 0.329796, 0.339870, 0.349499, 0.358715, 0.367545, 0.376015, 0.384150, 0.391971, 0.399498, 0.406751, 0.413746, 0.420499, 0.427026, 0.433340, 0.439453, 0.445378, 0.451125, 0.456705, 0.462127, 0.467400, 0.472532, 0.477531, 0.482404, 0.487157, 0.491797, 0.496330, 0.500760, 0.505094, 0.509116, 0.513264, 0.517327, 0.521309, 0.525213, 0.529043, 0.532803, 0.536495, 0.540123, 0.543689, 0.547196, 0.550646, 0.554041, 0.557385, 0.560678, 0.563922, 0.567120, 0.570273, 0.573383, 0.576451, 0.579478, 0.582467, 0.585418, 0.588332, 0.591211, 0.594055, 0.596866, 0.599644, 0.602392, 0.605108, 0.607795, 0.610453, 0.613082, 0.615684, 0.618259, 0.620808, 0.623331, 0.625829, 0.628303, 0.630753, 0.633179, 0.635582, 0.637963, 0.640321, 0.642658, 0.644974, 0.647269, 0.649543, 0.651797, 0.653815, 0.656029, 0.658222, 0.660396, 0.662552, 0.664689, 0.666807, 0.668908, 0.670990, 0.673056, 0.675104, 0.677135, 0.679149, 0.681147, 0.683128, 0.685094, 0.687044, 0.688978, 0.690896, 0.692799, 0.694688, 0.696561, 0.698420, 0.700264, 0.702094, 0.703909, 0.705711, 0.707499, 0.709273, 0.711033, 0.712781, 0.714515, 0.716235, 0.717943, 0.719638, 0.721321, 0.722991, 0.724648, 0.726293, 0.727926, 0.729547, 0.731156, 0.732753, 0.734339, 0.735913, 0.737475, 0.739026, 0.740566, 0.742095, 0.743613, 0.745120, 0.746616, 0.748101, 0.749576, 0.751040, 0.752494, 0.753937, 0.755371, 0.756794, 0.758207, 0.759610, 0.761003, 0.762387, 0.763761, 0.765125, 0.766479, 0.767825, 0.769160, 0.770487, 0.771805, 0.773113, 0.774412, 0.775702, 0.776984, 0.778257, 0.779521, 0.780776, 0.782022, 0.783261, 0.784490, 0.785712, 0.786925, 0.788130, 0.789327, 0.790515, 0.791696, 0.792868, 0.794033, 0.795190, 0.796339, 0.797481, 0.798615, 0.799741, 0.800860, 0.801971, 0.803075, 0.804172, 0.805261, 0.806343, 0.807418, 0.808486, 0.809547, 0.810601, 0.811647, 0.812687, 0.813721, 0.814747, 0.815767, 0.816780, 0.817786, 0.818786, 0.819780, 0.820767, 0.821747, 0.822722, 0.823689, 0.824651, 0.825607, 0.826556, 0.827499, 0.828436, 0.829367, 0.830292, 0.831212, 0.832125, 0.833032, 0.833934, 0.834830, 0.835720, 0.836605, 0.837484, 0.838357, 0.839225, 0.840088, 0.840945, 0.841796, 0.842642, 0.843483, 0.844319, 0.845149, 0.845974, 0.846794, 0.847609, 0.848419, 0.849223, 0.850023, 0.850818, 0.851608, 0.852392, 0.853172, 0.853947, 0.854718, 0.855483, 0.856244, 0.857000, 0.857752, 0.858499, 0.859241, 0.859979, 0.860712, 0.861441, 0.862165, 0.862885, 0.863600, 0.864311, 0.865018, 0.865720, 0.866418, 0.867112, 0.867802, 0.868488, 0.869169, 0.869846, 0.870519, 0.871188, 0.871854, 0.872515, 0.873172, 0.873825, 0.874474, 0.875120, 0.875761, 0.876399, 0.877033, 0.877663, 0.878289, 0.878911, 0.879530, 0.880146, 0.880757, 0.881365, 0.881969, 0.882570, 0.883167, 0.883761, 0.884351, 0.884938, 0.885521, 0.886101, 0.886677, 0.887250, 0.887820, 0.888387, 0.888950, 0.889509, 0.890066, 0.890619, 0.891169, 0.891716, 0.892259, 0.892800, 0.893337, 0.893872, 0.894403, 0.894931, 0.895456, 0.895978, 0.896497, 0.897013, 0.897526, 0.898036, 0.898543, 0.899047, 0.899549, 0.900047, 0.900543, 0.901036, 0.901526, 0.902013, 0.902497, 0.902979, 0.903458, 0.903934, 0.904407, 0.904878, 0.905346, 0.905812, 0.906275, 0.906735, 0.907193, 0.907648, 0.908100, 0.908550, 0.908998, 0.909443, 0.909885, 0.910325, 0.910762, 0.911198, 0.911630, 0.912060, 0.912488, 0.912914, 0.913337, 0.913757, 0.914176, 0.914592, 0.915005, 0.915417, 0.915826, 0.916233, 0.916638, 0.917040, 0.917440, 0.917838, 0.918234, 0.918628, 0.919019, 0.919408, 0.919796, 0.920181, 0.920564, 0.920944, 0.921323, 0.921700, 0.922075, 0.922447, 0.922818, 0.923186, 0.923553, 0.923917, 0.924280, 0.924641, 0.924999, 0.925356, 0.925711, 0.926064, 0.926415, 0.926764, 0.927111, 0.927456, 0.927800, 0.928141, 0.928481, 0.928819, 0.929155, 0.929490, 0.929822, 0.930153, 0.930482, 0.930809, 0.931135, 0.931459, 0.931781, 0.932101, 0.932420, 0.932737, 0.933052, 0.933365, 0.933677, 0.933988, 0.934296, 0.934603, 0.934909, 0.935213, 0.935515, 0.935815, 0.936114, 0.936412, 0.936708, 0.937002, 0.937295, 0.937586, 0.937876, 0.938164, 0.938451, 0.938736, 0.939020, 0.939302, 0.939583, 0.939862, 0.940140, 0.940416, 0.940691, 0.940965, 0.941237, 0.941507, 0.941777, 0.942045, 0.942311, 0.942576, 0.942840, 0.943103, 0.943364, 0.943623, 0.943882, 0.944139, 0.944395, 0.944649, 0.944902, 0.945154, 0.945405, 0.945654, 0.945902, 0.946149, 0.946394, 0.946638, 0.946881, 0.947123, 0.947363, 0.947603, 0.947841, 0.948078, 0.948313, 0.948548, 0.948781, 0.949013, 0.949244, 0.949474, 0.949702, 0.949930, 0.950156, 0.950381, 0.950605, 0.950828, 0.951050, 0.951270, 0.951490, 0.951708, 0.951926, 0.952142, 0.952357, 0.952571, 0.952784, 0.952996, 0.953207, 0.953417, 0.953626, 0.953833, 0.954040, 0.954246, 0.954451, 0.954654, 0.954857, 0.955059, 0.955259, 0.955459, 0.955657, 0.955855, 0.956052, 0.956248, 0.956442, 0.956636, 0.956829, 0.957021, 0.957212, 0.957402, 0.957591, 0.957779, 0.957966, 0.958153, 0.958338, 0.958522, 0.958706, 0.958889, 0.959071, 0.959251, 0.959431, 0.959611, 0.959789, 0.959966, 0.960143, 0.960318, 0.960493, 0.960667, 0.960840, 0.961013, 0.961184, 0.961355, 0.961524, 0.961693, 0.961862, 0.962029, 0.962195, 0.962361, 0.962526, 0.962690, 0.962854, 0.963016, 0.963178, 0.963339, 0.963499, 0.963659, 0.963817, 0.963975, 0.964132, 0.964289, 0.964444, 0.964599, 0.964754, 0.964907, 0.965060, 0.965212, 0.965363, 0.965513, 0.965663, 0.965812, 0.965961, 0.966108, 0.966255, 0.966402, 0.966547, 0.966692, 0.966836, 0.966980, 0.967123, 0.967265, 0.967407, 0.967547, 0.967688, 0.967827, 0.967966, 0.968104, 0.968242, 0.968379, 0.968515, 0.968650, 0.968785, 0.968920, 0.969053, 0.969186, 0.969319, 0.969451, 0.969582, 0.969713, 0.969843, 0.969972, 0.970101, 0.970229, 0.970356, 0.970483, 0.970610, 0.970736, 0.970861, 0.970985, 0.971110, 0.971233, 0.971356, 0.971478, 0.971600, 0.971721, 0.971842, 0.971962, 0.972081, 0.972200, 0.972319, 0.972437, 0.972554, 0.972671, 0.972787, 0.972903, 0.973018, 0.973133, 0.973247, 0.973360, 0.973473, 0.973586, 0.973698, 0.973809, 0.973920, 0.974031, 0.974141, 0.974250, 0.974359, 0.974468, 0.974576, 0.974683, 0.974790, 0.974897, 0.975003, 0.975108, 0.975213, 0.975318, 0.975422, 0.975526, 0.975629, 0.975731, 0.975834, 0.975935, 0.976037, 0.976138, 0.976238, 0.976338, 0.976437, 0.976536, 0.976635, 0.976733, 0.976831, 0.976928, 0.977025, 0.977121, 0.977217, 0.977312, 0.977407, 0.977502, 0.977596, 0.977690, 0.977783, 0.977876, 0.977969, 0.978061, 0.978153, 0.978244, 0.978335, 0.978425, 0.978515, 0.978605, 0.978694, 0.978783, 0.978871, 0.978959, 0.979047, 0.979134, 0.979221, 0.979308, 0.979394, 0.979479, 0.979565, 0.979650, 0.979734, 0.979818, 0.979902, 0.979986, 0.980069, 0.980151, 0.980234, 0.980316, 0.980397, 0.980479, 0.980560, 0.980640, 0.980720, 0.980800, 0.980879, 0.980959, 0.981037, 0.981116, 0.981194, 0.981271, 0.981349, 0.981426, 0.981503, 0.981579, 0.981655, 0.981731, 0.981806, 0.981881, 0.981956, 0.982030, 0.982104, 0.982178, 0.982251, 0.982324, 0.982397, 0.982469, 0.982541, 0.982613, 0.982685, 0.982756, 0.982827, 0.982897, 0.982967, 0.983037, 0.983107, 0.983176, 0.983245, 0.983314, 0.983382, 0.983450, 0.983518, 0.983586, 0.983653, 0.983720, 0.983786, 0.983853, 0.983919, 0.983985, 0.984050, 0.984115, 0.984180, 0.984245, 0.984309, 0.984373, 0.984437, 0.984500, 0.984564, 0.984627, 0.984689, 0.984752, 0.984814, 0.984876, 0.984937, 0.984999, 0.985060, 0.985121, 0.985181, 0.985242, 0.985302
};

static const double MI_map_64qam_axis[MI_MAP_64QAM_SIZE] = {
  0.250000, 0.460000, 0.670000, 0.880000, 1.090000, 1.300000, 1.510000, 1.720000, 1.930000, 2.140000, 2.350000, 2.560000, 2.770000, 2.980000, 3.190000, 3.400000, 3.610000, 3.820000, 4.030000, 4.240000, 4.450000, 4.660000, 4.870000, 5.080000, 5.290000, 5.500000, 5.710000, 5.920000, 6.130000, 6.340000, 6.550000, 6.760000, 6.970000, 7.180000, 7.390000, 7.600000, 7.810000, 8.020000, 8.230000, 8.440000, 8.650000, 8.860000, 9.070000, 9.280000, 9.490000, 9.700000, 9.910000, 10.120000, 10.330000, 10.540000, 10.750000, 10.960000, 11.170000, 11.380000, 11.590000, 11.800000, 12.010000, 12.220000, 12.430000, 12.640000, 12.850000, 13.060000, 13.270000, 13.480000, 13.690000, 13.900000, 14.110000, 14.320000, 14.530000, 14.740000, 14.950000, 15.160000, 15.370000, 15.580000, 15.790000, 16.000000, 16.210000, 16.420000, 16.630000, 16.840000, 17.050000, 17.260000, 17.470000, 17.680000, 17.890000, 18.100000, 18.310000, 18.520000, 18.730000, 18.940000, 19.150000, 19.360000, 19.570000, 19.780000, 19.990000, 20.200000, 20.410000, 20.620000, 20.830000, 21.040000, 21.250000, 21.460000, 21.670000, 21.880000, 22.090000, 22.300000, 22.510000, 22.720000, 22.930000, 23.140000, 23.350000, 23.560000, 23.770000, 23.980000, 24.190000, 24.400000, 24.610000, 24.820000, 25.030000, 25.240000, 25.450000, 25.660000, 25.870000, 26.080000, 26.290000, 26.500000, 26.710000, 26.920000, 27.130000, 27.340000, 27.550000, 27.760000, 27.970000, 28.180000, 28.390000, 28.600000, 28.810000, 29.020000, 29.230000, 29.440000, 29.650000, 29.860000, 30.070000, 30.280000, 30.490000, 30.700000, 30.910000, 31.120000, 31.330000, 31.540000, 31.750000, 31.960000, 32.170000, 32.380000, 32.590000, 32.800000, 33.010000, 33.220000, 33.430000, 33.640000, 33.850000, 34.060000, 34.270000, 34.480000, 34.690000, 34.900000, 35.110000, 35.320000, 35.530000, 35.740000, 35.950000, 36.160000, 36.370000, 36.580000, 36.790000, 37.000000, 37.210000, 37.420000, 37.630000, 37.840000, 38.050000, 38.260000, 38.470000, 38.680000, 38.890000, 39.100000, 39.310000, 39.520000, 39.730000, 39.940000, 40.150000, 40.360000, 40.570000, 40.780000, 40.990000, 41.200000, 41.410000, 41.620000, 41.830000, 42.040000, 42.250000, 42.460000, 42.670000, 42.880000, 43.090000, 43.300000, 43.510000, 43.720000, 43.930000, 44.140000, 44.350000, 44.560000, 44.770000, 44.980000, 45.190000, 45.400000, 45.610000, 45.820000, 46.030000, 46.240000, 46.450000, 46.660000, 46.870000, 47.080000, 47.290000, 47.500000, 47.710000, 47.920000, 48.130000, 48.340000, 48.550000, 48.760000, 48.970000, 49.180000, 49.390000, 49.600000, 49.810000, 50.020000, 50.230000, 50.440000, 50.650000, 50.860000, 51.070000, 51.280000, 51.490000, 51.700000, 51.910000, 52.120000, 52.330000, 52.540000, 52.750000, 52.960000, 53.170000, 53.380000, 53.590000, 53.800000, 54.010000, 54.220000, 54.430000, 54.640000, 54.850000, 55.060000, 55.270000, 55.480000, 55.690000, 55.900000, 56.110000, 56.320000, 56.530000, 56.740000, 56.950000, 57.160000, 57.370000, 57.580000, 57.790000, 58.000000, 58.210000, 58.420000, 58.630000, 58.840000, 59.050000, 59.260000, 59.470000, 59.680000, 59.890000, 60.100000, 60.310000, 60.520000, 60.730000, 60.940000, 61.150000, 61.360000, 61.570000, 61.780000, 61.990000, 62.200000, 62.410000, 62.620000, 62.830000, 63.040000, 63.250000, 63.460000, 63.670000, 63.880000, 64.090000, 64.300000, 64.510000, 64.720000, 64.930000, 65.140000, 65.350000, 65.560000, 65.770000, 65.980000, 66.190000, 66.400000, 66.610000, 66.820000, 67.030000, 67.240000, 67.450000, 67.660000, 67.870000, 68.080000, 68.290000, 68.500000, 68.710000, 68.920000, 69.130000, 69.340000, 69.550000, 69.760000, 69.970000, 70.180000, 70.390000, 70.600000, 70.810000, 71.020000, 71.230000, 71.440000, 71.650000, 71.860000, 72.070000, 72.280000, 72.490000, 72.700000, 72.910000, 73.120000, 73.330000, 73.540000, 73.750000, 73.960000, 74.170000, 74.380000, 74.590000, 74.800000, 75.010000, 75.220000, 75.430000, 75.640000, 75.850000, 76.060000, 76.270000, 76.480000, 76.690000, 76.900000, 77.110000, 77.320000, 77.530000, 77.740000, 77.950000, 78.160000, 78.370000, 78.580000, 78.790000, 79.000000, 79.210000, 79.420000, 79.630000, 79.840000, 80.050000, 80.260000, 80.470000, 80.680000, 80.890000, 81.100000, 81.310000, 81.520000, 81.730000, 81.940000, 82.150000, 82.360000, 82.570000, 82.780000, 82.990000, 83.200000, 83.410000, 83.620000, 83.830000, 84.040000, 84.250000, 84.460000, 84.670000, 84.880000, 85.090000, 85.300000, 85.510000, 85.720000, 85.930000, 86.140000, 86.350000, 86.560000, 86.770000, 86.980000, 87.190000, 87.400000, 87.610000, 87.820000, 88.030000, 88.240000, 88.450000, 88.660000, 88.870000, 89.080000, 89.290000, 89.500000, 89.710000, 89.920000, 90.130000, 90.340000, 90.550000, 90.760000, 90.970000, 91.180000, 91.390000, 91.600000, 91.810000, 92.020000, 92.230000, 92.440000, 92.650000, 92.860000, 93.070000, 93.280000, 93.490000, 93.700000, 93.910000, 94.120000, 94.330000, 94.540000, 94.750000, 94.960000, 95.170000, 95.380000, 95.590000, 95.800000, 96.010000, 96.220000, 96.430000, 96.640000, 96.850000, 97.060000, 97.270000, 97.480000, 97.690000, 97.900000, 98.110000, 98.320000, 98.530000, 98.740000, 98.950000, 99.160000, 99.370000, 99.580000, 99.790000, 100.000000, 100.210000, 100.420000, 100.630000, 100.840000, 101.050000, 101.260000, 101.470000, 101.680000, 101.890000, 102.100000, 102.310000, 102.520000, 102.730000, 102.940000, 103.150000, 103.360000, 103.570000, 103.780000, 103.990000, 104.200000, 104.410000, 104.620000, 104.830000, 105.040000, 105.250000, 105.460000, 105.670000, 105.880000, 106.090000, 106.300000, 106.510000, 106.720000, 106.930000, 107.140000, 107.350000, 107.560000, 107.770000, 107.980000, 108.190000, 108.400000, 108.610000, 108.820000, 109.030000, 109.240000, 109.450000, 109.660000, 109.870000, 110.080000, 110.290000, 110.500000, 110.710000, 110.920000, 111.130000, 111.340000, 111.550000, 111.760000, 111.970000, 112.180000, 112.390000, 112.600000, 112.810000, 113.020000, 113.230000, 113.440000, 113.650000, 113.860000, 114.070000, 114.280000, 114.490000, 114.700000, 114.910000, 115.120000, 115.330000, 115.540000, 115.750000, 115.960000, 116.170000, 116.380000, 116.590000, 116.800000, 117.010000, 117.220000, 117.430000, 117.640000, 117.850000, 118.060000, 118.270000, 118.480000, 118.690000, 118.900000, 119.110000, 119.320000, 119.530000, 119.740000, 119.950000, 120.160000, 120.370000, 120.580000, 120.790000, 121.000000, 121.210000, 121.420000, 121.630000, 121.840000, 122.050000, 122.260000, 122.470000, 122.680000, 122.890000, 123.100000, 123.310000, 123.520000, 123.730000, 123.940000, 124.150000, 124.360000, 124.570000, 124.780000, 124.990000, 125.200000, 125.410000, 125.620000, 125.830000, 126.040000, 126.250000, 126.460000, 126.670000, 126.880000, 127.090000, 127.300000, 127.510000, 127.720000, 127.930000, 128.140000, 128.350000, 128.560000, 128.770000, 128.980000, 129.190000, 129.400000, 129.610000, 129.820000, 130.030000, 130.240000, 130.450000, 130.660000, 130.870000, 131.080000, 131.290000, 131.500000, 131.710000, 131.920000, 132.130000, 132.340000, 132.550000, 132.760000, 132.970000, 133.180000, 133.390000, 133.600000, 133.810000, 134.020000, 134.230000, 134.440000, 134.650000, 134.860000, 135.070000, 135.280000, 135.490000, 135.700000, 135.910000, 136.120000, 136.330000, 136.540000, 136.750000, 136.960000, 137.170000, 137.380000, 137.590000, 137.800000, 138.010000, 138.220000, 138.430000, 138.640000, 138.850000, 139.060000, 139.270000, 139.480000, 139.690000, 139.900000, 140.110000, 140.320000, 140.530000, 140.740000, 140.950000, 141.160000, 141.370000, 141.580000, 141.790000, 142.000000, 142.210000, 142.420000, 142.630000, 142.840000, 143.050000, 143.260000, 143.470000, 143.680000, 143.890000, 144.100000, 144.310000, 144.520000, 144.730000, 144.940000, 145.150000, 145.360000, 145.570000, 145.780000, 145.990000, 146.200000, 146.410000, 146.620000, 146.830000, 147.040000, 147.250000, 147.460000, 147.670000, 147.880000, 148.090000, 148.300000, 148.510000, 148.720000, 148.930000, 149.140000, 149.350000, 149.560000, 149.770000, 149.980000, 150.190000, 150.400000, 150.610000, 150.820000, 151.030000, 151.240000, 151.450000, 151.660000, 151.870000, 152.080000, 152.290000, 152.500000, 152.710000, 152.920000, 153.130000, 153.340000, 153.550000, 153.760000, 153.970000, 154.180000, 154.390000, 154.600000, 154.810000, 155.020000, 155.230000, 155.440000, 155.650000, 155.860000, 156.070000, 156.280000, 156.490000, 156.700000, 156.910000, 157.120000, 157.330000, 157.540000, 157.750000, 157.960000
};




static const double bEcrTable [9][38] = {
  // CB of 40 bits
  {
    0.02472, 0.06352, 0.09516, // QPSK retx
    0.1777, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },  
  // CB of 104 bits
  {
    0.01940, 0.05020, 0.07592, // QPSK retx
    0.1423, 0.1753, 0.1882, 0.2499, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },
  // CB of 160
  {
    0.01820, 0.04688, 0.07082, // QPSK retx
    0.1354, 0.1655, 0.1812, 0.2351, 0.2873, 0.3462, -1.000, -1.000, -1.000, -1.0000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },
  // CB of 256
  {
    0.01728, 0.04488, 0.06786, // QPSK retx
    0.1304, 0.1584, 0.1735, 0.2265, 0.2782, 0.3340, 0.3927, 0.4785, 0.5566, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000  // 64QAM
  },
  // CB of 512
  {
    0.01658, 0.04332, 0.06550, // QPSK retx
    0.1257, 0.1528, 0.1667, 0.2188, 0.2680, 0.3229, 0.3818, 0.4607, 0.5373, 0.6081, // QPSK
    0.15004, 0.18266, 0.24084, // 16 QAM retx
    0.3783, 0.4049, 0.4472, 0.4975, 0.5556, -1.000, -1.000, //16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000  // 64QAM
  },
  // CB of 1024
  {
    0.01622, 0.04216, 0.06402, // QPSK retx
    0.1224, 0.1497, 0.1638, 0.2139, 0.2636, 0.3195, 0.3768, 0.4520, 0.5269, 0.5963, // QPSK
    0.14846, 0.18102, 0.237880, // 16QAM retx
    0.3754, 0.3979, 0.4399, 0.4894, 0.5464, 0.6034, 0.6619, // 16QAM
    0.13938, 0.19212, 0.28890, // 64QAM retx
    0.50662, 0.52226, 0.5627, 0.6089, 0.6577, 0.7049, 0.7508, -1.000, -1.000, -1.000, -1.000, -1.000  //64QAM
  },
  // CB of 2560
  {
    0.01600, 0.04164, 0.06320, // QPSK retx
    0.1211, 0.1480, 0.1615, 0.2119, 0.2611, 0.3157, 0.3735, 0.4458, 0.5205, 0.5902, // QPSK
    0.14484, 0.17770, 0.23558, // 16 QAM retx
    0.3729, 0.3939, 0.4351, 0.4851, 0.5416, 0.5976, 0.6554, // 16QAM
    0.13770, 0.18336, 0.27600, // 64 QAM retx
    0.50028, 0.51888, 0.5619, 0.6056, 0.6521, 0.6982, 0.7441, 0.7874, 0.8315, 0.8735, 0.9089, 0.9369  // 64QAM
  },
  // CB of 4032
  {
    0.01598, 0.04164, 0.06300, // QPSK retx
    0.1208, 0.1477, 0.1612, 0.2112, 0.2606, 0.3153, 0.3728, 0.4441, 0.5185, 0.5882,  // QPSK
    0.169280, 0.199820, 0.25520, // 16 QAM retx
    0.3864, 0.3921, 0.4338, 0.4871, 0.5386, 0.5940, 0.6527,  // 16QAM
    0.13754, 0.18956, 0.28408, // 64QAM retx
    0.50316, 0.51872, 0.5591, 0.6027, 0.6512, 0.6981, 0.7437, 0.7873, 0.8301, 0.8702, 0.9082, 0.9339  // 64QAM
  },
  // CB of 6144
  {
    0.01598, 0.04154, 0.06288, // QPSK retx
    0.1207, 0.1474, 0.1612, 0.2111, 0.2605, 0.3153, 0.3726, 0.4439, 0.5193, 0.5882,  // QPSK
    0.14490, 0.17742, 0.23514, // 16QAM retx
    0.3724, 0.3921, 0.4339, 0.4833, 0.5407, 0.5952, 0.6528, // 16QAM
    0.13752, 0.18244, 0.27578,  // 64QAM retx
    0.49780, 0.51606, 0.5600, 0.6027, 0.6494, 0.6948, 0.7407, 0.7842, 0.8284, 0.8692, 0.9058, 0.9325  // 64QAM
  },
};
  
  
static const double cEcrTable [9][38] = {
  // CB of 40 bits
  {
    0.00543, 0.01337, 0.01969, // QPSK retx
    0.0342, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000,    -1.000, -1.000 // 64 QAM
  },
  // CB of 104 bits
  {
    0.00301, 0.00749, 0.01071, // QPSK retx
    0.0198, 0.0239, 0.0248, 0.0320, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },
  // CB of 160 bits
  {
    0.00245, 0.00589, 0.00843, // QPSK retx
    0.0157, 0.0190, 0.0204, 0.0252, 0.0310, 0.0348, -1.0000, -1.000, -1.000, -1.000, //QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },
  // CB of 256 bits
  {
    0.00187, 0.00453, 0.00699, // QPSK retx
    0.0123, 0.0149, 0.0163, 0.0212, 0.0252, 0.0298, 0.0304, 0.0341, 0.0382, -1.000, // QPSK
    -1.000, -1.000, -1.000, // 16QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000
  },
  // CB of 512 bits
  {
    0.00135, 0.00319, 0.00469, // QPSK retx
    0.0085, 0.0106, 0.0109, 0.0140, 0.0178, 0.0217, 0.0219, 0.0249, 0.0270, 0.0292, // QPSK
    0.01027, 0.01197, 0.01485, // 16QAM retx
    0.0202, 0.0206, 0.0220, 0.0235, 0.0236, -1.000, -1.000, // 16 QAM
    -1.000, -1.000, -1.000, // 64QAM retx
    -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000
  },
  // CB of 1024 bits
  {
    0.00093, 0.00239, 0.00327, // QPSK retx
    0.0061, 0.0074, 0.0078, 0.0102, 0.0121, 0.0138, 0.0163, 0.0178, 0.0207, 0.0198, // QPSK
    0.00725, 0.00879, 0.01015, // 16QAM retx
    0.0141, 0.0137, 0.0154, 0.0164, 0.0175, 0.0188, 0.0188, // 16QAM
    0.00705, 0.01111, 0.01359, // 64QAM retx
    0.01661, 0.01655, 0.0157, 0.0169, 0.0185, 0.0189, 0.0200, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM
  },
  // CB of 2560 bits
  {
    0.00059, 0.00145, 0.00209, // QPSK retx
    0.0040, 0.0047, 0.0050, 0.0063, 0.0079, 0.0091, 0.0101, 0.0117, 0.0123, 0.0129, // QPSK
    0.00419, 0.00515, 0.00649, // 16QAM retx
    0.0083, 0.0091, 0.0095, 0.0102, 0.0112, 0.0114, 0.0119, // 16QAM
    0.00451, 0.00597, 0.00791, // 64QAM retx
    0.00951, 0.00943, 0.0096, 0.0104, 0.0109, 0.0108, 0.0118, 0.0122, 0.0117, 0.0110, 0.0097, 0.0085 // 64QAM
  },
  // CB of 4032 bits
  {
    0.00045, 0.00111, 0.00173, // QPSK retx
    0.0032, 0.0038, 0.0039, 0.0051, 0.0063, 0.0072, 0.0079, 0.0084, 0.0100, 0.0106, // QPSK
    0.00577, 0.00615, 0.00723, // 16QAM retx
    0.0092, 0.0074, 0.0078, 0.0090, 0.0084, 0.0089, 0.0092, // 16 QAM
    0.00369, 0.00565, 0.00737, // 64QAM retx
    0.00795, 0.0080, 0.0080, 0.0081, 0.0090, 0.0091, 0.0095, 0.0096, 0.0094, 0.0086, 0.0078, 0.0071 // 64QAM
  },
  // CB of 6144 bits
  {
    0.00037, 0.00093, 0.00141, // QPSK retx
    0.0025, 0.0032, 0.0032, 0.0042, 0.0054, 0.0059, 0.0064, 0.0073, 0.0081, 0.0076, // QPSK
    0.00273, 0.00351, 0.00417, // 16QAM retx
    0.0056, 0.0058, 0.0064, 0.0070, 0.0068, 0.0074, 0.0080, // 16QAM
    0.00303, 0.00377, 0.00507, // 64QAM retx
    0.0060, 0.00609, 0.0061, 0.0066, 0.0069, 0.0080, 0.0081, 0.0080, 0.0077, 0.0068, 0.0066, 0.0058 // 64QAM
  }
    
};


double 
LteMiErrorModel::Mib (const SpectrumValue& sinr, const std::vector<int>& map, uint8_t mcs)
{
  NS_LOG_FUNCTION (sinr << &map << (uint32_t) mcs);
  
  double MI;
  double MIsum = 0.0;
  SpectrumValue sinrCopy = sinr;
  
  for (uint32_t i = 0; i < map.size (); i++)
    {
      double sinrLin = sinrCopy[map.at (i)];
      if (mcs <= MI_QPSK_MAX_ID) // QPSK
        {

          if (sinrLin > MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1])
            {
              MI = 1;
            }
          else 
            { 
              // since the values in MI_map_qpsk_axis are uniformly spaced, we have
              // index = ((sinrLin - value[0]) / (value[SIZE-1] - value[0])) * (SIZE-1)
              // the scaling coefficient is always the same, so we use a static const
              // to speed up the calculation
              static const double scalingCoeffQpsk = 
                (MI_MAP_QPSK_SIZE - 1) / (MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1] - MI_map_qpsk_axis[0]);
              double sinrIndexDouble = (sinrLin -  MI_map_qpsk_axis[0]) * scalingCoeffQpsk + 1;
              uint32_t sinrIndex = std::max(0.0, std::floor (sinrIndexDouble));
              NS_ASSERT_MSG (sinrIndex < MI_MAP_QPSK_SIZE, "MI map out of data");
              MI = MI_map_qpsk[sinrIndex];
            }
        }
      else
        {
          if (mcs > MI_QPSK_MAX_ID && mcs <= MI_16QAM_MAX_ID )	// 16-QAM
            {
              if (sinrLin > MI_map_16qam_axis[MI_MAP_16QAM_SIZE-1])
                {
                  MI = 1;
                }
              else 
                {
                  // since the values in MI_map_16QAM_axis are uniformly spaced, we have
                  // index = ((sinrLin - value[0]) / (value[SIZE-1] - value[0])) * (SIZE-1)
                  // the scaling coefficient is always the same, so we use a static const
                  // to speed up the calculation
                  static const double scalingCoeff16qam = 
                    (MI_MAP_16QAM_SIZE - 1) / (MI_map_16qam_axis[MI_MAP_16QAM_SIZE-1] - MI_map_16qam_axis[0]);
                  double sinrIndexDouble = (sinrLin -  MI_map_16qam_axis[0]) * scalingCoeff16qam + 1;
                  uint32_t sinrIndex = std::max(0.0, std::floor (sinrIndexDouble));
                  NS_ASSERT_MSG (sinrIndex < MI_MAP_16QAM_SIZE, "MI map out of data");
                  MI = MI_map_16qam[sinrIndex];
                }
            }
          else // 64-QAM
            {
              if (sinrLin > MI_map_64qam_axis[MI_MAP_64QAM_SIZE-1])
                {
                  MI = 1;
                }
              else
                {
                  // since the values in MI_map_64QAM_axis are uniformly spaced, we have
                  // index = ((sinrLin - value[0]) / (value[SIZE-1] - value[0])) * (SIZE-1)
                  // the scaling coefficient is always the same, so we use a static const
                  // to speed up the calculation
                  static const double scalingCoeff64qam = 
                    (MI_MAP_64QAM_SIZE - 1) / (MI_map_64qam_axis[MI_MAP_64QAM_SIZE-1] - MI_map_64qam_axis[0]);
                  double sinrIndexDouble = (sinrLin -  MI_map_64qam_axis[0]) * scalingCoeff64qam + 1;
                  uint32_t sinrIndex = std::max(0.0, std::floor (sinrIndexDouble));
                  NS_ASSERT_MSG (sinrIndex < MI_MAP_64QAM_SIZE, "MI map out of data");
                  MI = MI_map_64qam[sinrIndex];
                }
            }
        }
      NS_LOG_LOGIC (" RB " << map.at (i) << "Minimum SNR = " << 10 * std::log10 (sinrLin) << " dB, " << sinrLin << " V, MCS = " << (uint16_t)mcs << ", MI = " << MI);
      MIsum += MI;
    }
  MI = MIsum / map.size ();
  NS_LOG_LOGIC (" MI = " << MI);
  return MI;
}


double 
LteMiErrorModel::MappingMiBler (double mib, uint8_t ecrId, uint16_t cbSize)
{
  NS_LOG_FUNCTION (mib << (uint32_t) ecrId << (uint32_t) cbSize);
  double b = 0;
  double c = 0;

  NS_ASSERT_MSG (ecrId <= MI_64QAM_BLER_MAX_ID, "ECR out of range [0..37]: " << (uint16_t) ecrId);
  int cbIndex = 1;
  while ((cbIndex < 9)&&(cbMiSizeTable[cbIndex]<= cbSize))
    {
      cbIndex++;
    }
  cbIndex--;
  NS_LOG_LOGIC (" ECRid " << (uint16_t)ecrId << " ECR " << BlerCurvesEcrMap[ecrId] << " CB size " << cbSize << " CB size curve " << cbMiSizeTable[cbIndex]);

  b = bEcrTable[cbIndex][ecrId];
  if (b<0.0)
    {
      //take the lowest CB size including this CB for removing CB size
      //quatization errors
      int i = cbIndex;
      while ((i<9)&&(b<0))
        {
          b = bEcrTable[i++][ecrId];
        }
    }
  c = cEcrTable[cbIndex][ecrId];
  if (c<0.0)
    {
      //take the lowest CB size including this CB for removing CB size
      //quatization errors
      int i = cbIndex;
      while ((i<9)&&(c<0))
        {
          c = cEcrTable[i++][ecrId];
        }
    }
  // see IEEE802.16m EMD formula 55 of section 4.3.2.1
  double bler = 0.5*( 1 - erf((mib-b)/(sqrt(2)*c)) );
  NS_LOG_LOGIC ("MIB: " << mib << " BLER:" << bler << " b:" << b << " c:" << c);
  return bler;
}



double
LteMiErrorModel::GetPcfichPdcchError (const SpectrumValue& sinr)
{
  NS_LOG_FUNCTION (sinr);
  double MI;
  double MIsum = 0.0;
  SpectrumValue sinrCopy = sinr;
  Values::iterator sinrIt = sinrCopy.ValuesBegin ();
  uint16_t rb = 0;
  NS_ASSERT (sinrIt!=sinrCopy.ValuesEnd ());
  while (sinrIt!=sinrCopy.ValuesEnd ())
    {
      double sinrLin = *sinrIt;
      if (sinrLin > MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1])
        {
          MI = 1;
        }
      else 
        { 
          // since the values in MI_map_qpsk_axis are uniformly spaced, we have
          // index = ((sinrLin - value[0]) / (value[SIZE-1] - value[0])) * (SIZE-1)
              // the scaling coefficient is always the same, so we use a static const
              // to speed up the calculation
          static const double scalingCoeffQpsk = 
            (MI_MAP_QPSK_SIZE - 1) / (MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1] - MI_map_qpsk_axis[0]);
          double sinrIndexDouble = (sinrLin -  MI_map_qpsk_axis[0]) * scalingCoeffQpsk + 1;
          uint32_t sinrIndex = std::max(0.0, std::floor (sinrIndexDouble));
          NS_ASSERT_MSG (sinrIndex < MI_MAP_QPSK_SIZE, "MI map out of data");
          MI = MI_map_qpsk[sinrIndex];
        }
      MIsum += MI;
      sinrIt++;
      rb++;
    }
  MI = MIsum / rb;
  // return to the effective SINR value
  int j = 0;
  double esinr = 0.0;
  while ((j<MI_MAP_QPSK_SIZE)&&(MI_map_qpsk[j] < MI))
    {
      j++;
    }
  if (MI > MI_map_qpsk[MI_MAP_QPSK_SIZE-1])
    {
      esinr = MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1];
    }
  else 
    {
      NS_ASSERT_MSG (j<MI_MAP_QPSK_SIZE, "MI map out of data");
      // take the closest value (when possible)  
      if (j>0)
        {
          if ((MI_map_qpsk[j]-MI)<(MI-MI_map_qpsk[j-1]))
            {
              esinr = MI_map_qpsk_axis[j];
            }
          else
            {
              esinr = MI_map_qpsk_axis[j-1];
            }
        }
      else
        {
          esinr = MI_map_qpsk_axis[0];
        }
    }

  double esirnDb = 10*log10 (esinr); 
//   NS_LOG_DEBUG ("Effective SINR " << esirnDb << " max " << 10*log10 (MI_map_qpsk [MI_MAP_QPSK_SIZE-1]));
  uint16_t i = 0;
  double errorRate = 0.0;
  while ((i<PDCCH_PCFICH_CURVE_SIZE)&&(PdcchPcfichBlerCurveXaxis[i] < esirnDb))
    {
      i++;
    }
  if (esirnDb > PdcchPcfichBlerCurveXaxis[PDCCH_PCFICH_CURVE_SIZE-1])
    {
      errorRate = 0.0;
    }
  else 
    {
      NS_ASSERT_MSG (i<PDCCH_PCFICH_CURVE_SIZE, "PDCCH-PCFICH map out of data");
      errorRate = PdcchPcfichBlerCurveYaxis[i];
    }  
  
  return (errorRate);
}




TbStats_t
LteMiErrorModel::GetTbDecodificationStats (const SpectrumValue& sinr, const std::vector<int>& map, uint16_t size, uint8_t mcs, HarqProcessInfoList_t miHistory)
{
  NS_LOG_FUNCTION (sinr << &map << (uint32_t) size << (uint32_t) mcs);

  double tbMi = Mib(sinr, map, mcs);
  double MI = 0.0;
  double Reff = 0.0;
  NS_ASSERT (mcs < 29);
  if (miHistory.size ()>0)
    {
      // evaluate R_eff and MI_eff
      uint16_t codeBitsSum = 0;
      double miSum = 0.0;
      for (uint16_t i = 0; i < miHistory.size (); i++)
        {
          NS_LOG_DEBUG (" Sum MI " << miHistory.at (i).m_mi << " Ci " << miHistory.at (i).m_codeBits);
          codeBitsSum += miHistory.at (i).m_codeBits;
          miSum += (miHistory.at (i).m_mi*miHistory.at (i).m_codeBits);
        }
      codeBitsSum += (((double)size*8.0) / McsEcrTable [mcs]);
      miSum += (tbMi*(((double)size*8.0) / McsEcrTable [mcs]));
      Reff = miHistory.at (0).m_infoBits / (double)codeBitsSum; // information bits are the size of the first TB
      MI = miSum / (double)codeBitsSum;      
    }
  else
    {
      MI = tbMi;
    }
  NS_LOG_DEBUG (" MI " << MI << " Reff " << Reff << " HARQ " << miHistory.size ());
  // estimate CB size (according to sec 5.1.2 of TS 36.212)
  uint16_t Z = 6144; // max size of a codeblock (including CRC)
  uint32_t B = size * 8;
//   B = 1234;
  uint32_t L = 0;
  uint32_t C = 0; // no. of codeblocks
  uint32_t Cplus = 0; // no. of codeblocks with size K+
  uint32_t Kplus = 0; // no. of codeblocks with size K+
  uint32_t Cminus = 0; // no. of codeblocks with size K+
  uint32_t Kminus = 0; // no. of codeblocks with size K+
  uint32_t B1 = 0;
  uint32_t deltaK = 0;
  if (B <= Z)
    {
      // only one codeblock
      L = 0;
      C = 1;
      B1 = B;
    }
  else
    {
      L = 24;
      C = ceil ((double)B / ((double)(Z-L)));
      B1 = B + C * L;
    }
  // first segmentation: K+ = minimum K in table such that C * K >= B1
//   uint i = 0;
//   while (B1 > cbSizeTable[i] * C)
//     {
// //       NS_LOG_INFO (" K+ " << cbSizeTable[i] << " means " << cbSizeTable[i] * C);
//       i++;
//     }
//   uint16_t KplusId = i;
//   Kplus = cbSizeTable[i];

  // implement a modified binary search
  int min = 0;
  int max = 187;
  int mid = 0;
  do
    {
      mid = (min+max) / 2;
      if (B1 > cbSizeTable[mid]*C)
        {
          if (B1 < cbSizeTable[mid+1]*C)
            {
              break;
            }
          else
            {
              min = mid + 1;
            }
        }
      else
        {
          if (B1 > cbSizeTable[mid-1]*C)
            {
              break;
            }
          else
            {
              max = mid - 1;
            }
        }
  } while ((cbSizeTable[mid]*C != B1) && (min < max));
  // adjust binary search to the largest integer value of K containing B1
  if (B1 > cbSizeTable[mid]*C)
    {
      mid ++;
    }

  uint16_t KplusId = mid;
  Kplus = cbSizeTable[mid];


  if (C==1)
    {
      Cplus = 1;
      Cminus = 0;
      Kminus = 0;
    }
  else
    {
      // second segmentation size: K- = maximum K in table such that K < K+
      // -fstrict-overflow sensitive, see bug 1868
      Kminus = cbSizeTable[ KplusId > 1 ? KplusId - 1 : 0];
      deltaK = Kplus - Kminus;
      Cminus = floor ((((double) C * Kplus) - (double)B1) / (double)deltaK);
      Cplus = C - Cminus;
    }
  NS_LOG_INFO ("--------------------LteMiErrorModel: TB size of " << B << " needs of " << B1 << " bits reparted in " << C << " CBs as "<< Cplus << " block(s) of " << Kplus << " and " << Cminus << " of " << Kminus);

  double errorRate = 1.0;
  uint8_t ecrId = 0;
  if (miHistory.size ()==0)
    {
      // first tx -> get ECR from MCS
      ecrId = McsEcrBlerTableMapping[mcs];
      NS_LOG_DEBUG ("NO HARQ MCS " << (uint16_t)mcs << " ECR id " << (uint16_t)ecrId);
    }
  else
    {
      NS_LOG_DEBUG ("HARQ block no. " << miHistory.size ());
      // harq retx -> get closest ECR to Reff from available ones
      if (mcs <= MI_QPSK_MAX_ID)
        {
          // Modulation order 2
          uint8_t i = MI_QPSK_MAX_ID;
          while ((BlerCurvesEcrMap[i]>Reff)&&(i>0))
            {
              i--;
            }
          ecrId = i;
        }
      else if (mcs <= MI_16QAM_MAX_ID)
        {
          // Modulation order 4
          uint8_t i = MI_16QAM_MAX_ID;
          while ((BlerCurvesEcrMap[i]>Reff)&&(i>MI_QPSK_MAX_ID + 1))
            {
              i--;
            }
          ecrId = i;
        }
      else
        {
          // Modulation order 6
          uint8_t i = MI_64QAM_MAX_ID;
          while ((BlerCurvesEcrMap[i]>Reff)&&(i>MI_16QAM_MAX_ID + 1))
            {
              i--;
            }
          ecrId = i;
        }
      NS_LOG_DEBUG ("HARQ ECR " << (uint16_t)ecrId);
    }

  if (C!=1)
    {
      double cbler = MappingMiBler (MI, ecrId, Kplus);
      errorRate *= pow (1.0 - cbler, Cplus);
      cbler = MappingMiBler (MI, ecrId, Kminus);
      errorRate *= pow (1.0 - cbler, Cminus);
      errorRate = 1.0 - errorRate;
    }
  else
    {
      errorRate = MappingMiBler (MI, ecrId, Kplus);
    }

  NS_LOG_LOGIC (" Error rate " << errorRate);
  TbStats_t ret;
  ret.tbler = errorRate;
  ret.mi = tbMi;
  return ret;
}


  

} // namespace ns3

